<SECTION=Programs>
<program>
program test;						
	use string_utility_pak; 				
	print("","");		-- comment

	procedure my_proc(a);			-- comment	 			
	end my_proc;

end test;

<HELP>
SETL programs have the form 

	program prog_name; 
		use package_name,class_name,.;
		
		statements

		procedure name(parameter,parameter,..);	
			more_statements
		end name;
	
		procedure other_name(parameter,parameter,..);	
			other_statements
		end name;

	end prog_name;

The 'use' clause and subprocedures shown can be omitted. 'var' and 'const' statements declaring global variables can appear at the start of the program, after the 'use' clause.

Execution of a program begins with its first statement.  

<use>
	use xxx,xxx;

<HELP>
Use  clauses can appear at the start of programs, package bodies, and class bodies. They list the other packages and classes which these programs, packages, and classes wish to import. Library hierarchies can be built up by having higher level packages and classes import lower level packages and classes. Packages and classes can even 'use' (i.e. import) each other circularly, provided that their header blocks are compiled previous to their bodies. See the main SETL manual for an account of the name visbility rules which apply to names in imported packages.

<const>
	const xxx := xxx, xxx := xxx;

<HELP>
const  clauses can appear at the start of programs, procedures, package headers, class headers, package bodies, and class bodies. They serve to define the value of constants througout the scopes in which they are visible.

const clauses which appear in package or class headers make the named constants global in all programs, packages and classes which import them.
 
<var>
	var xxx , xxx := xxx;

<HELP>
var clauses can appear at the start of programs, procedures, package headers, class headers, package bodies, and class bodies. They define the scopes in which the variable names they list are visible.

var clauses which appear in package or class headers make the named variables global in all programs, packages and classes which import them.

var clauses which appear in class bodies have an important additional function: they define the 'instance variables' of the class; a private copy of each of these variables is created for each instance of the class. variables of which just one copy acessible to all such instances should be declared as 'class var' rather than 'var'.

<procedure>
procedure xxx(); 		-- 

	return zzz;
end xxx;

<HELP>
Procedure blocks have the form 

	procedure name(parameter,parameter,); 		
		statements
	end name;

The enclosed statements are executed when the procedure is invoked. The formal parameters listed must all be distinct. If the procedure is to modify one or more of its parameters when called, those parameters must be prefixed by one of the qualifiers 

Variable and parameter names appearing in a procedure are local to the procedure 
Procedures can contain declarations of their local variables, of constants used in the procedure, and can contin the bodies of nested subprocedures.

Return statements can be used within procedures. They have the form 

	return expn;				or 			return;

the latter equivalent to 'return OM;'

<return>
return zzz;

<HELP>
Return statements can be used within procedures. They have the form 

	return expn;				or 			return;

the latter equivalent to 'return OM;'

<if>
if xxx then

end if;

<HELP>
The 'if' statement can have one of several forms. Its simplest form is

		if condition then
			statements
		end if;

This executes the enclosed 'statements' if the 'condition' (whose value must be true or false)
has the value 'true'. The more elaborate form 

		if condition then
			statements
		else
			other_statements
		end if;

executes the enclosed 'other_statements' if the 'condition' has the value 'false'.

The still more elaborate form 

		if condition then
			statements
		elseif other_condition  then
			other_statements		
		else
			still_other_statements		
		end if;
		
tests a second 'other_condition' if 'condition' fails. This can have any number of 
'elseif' clauses, and can omit the 'else' clause.

<ifelse>
if xxx then

else

end if;

<HELP>
The 'if' statement can have one of several forms. Its simplest form is

		if condition then
			statements
		end if;

This executes the enclosed 'statements' if the 'condition' (whose value must be true or false)
has the value 'true'. The more elaborate form 

		if condition then
			statements
		else
			other_statements
		end if;

executes the enclosed 'other_statements' if the 'condition' has the value 'false'.

The still more elaborate form 

		if condition then
			statements
		elseif other_condition  then
			other_statements		
		else
			still_other_statements		
		end if;
		
tests a second 'other_condition' if 'condition' fails. This can have any number of 
'elseif' clauses, and can omit the 'else' clause.

<ifelseif>
if xxx then

elseif xxx  then

else

end if;

<HELP>
The 'if' statement can have one of several forms. Its simplest form is

		if condition then
			statements
		end if;

This executes the enclosed 'statements' if the 'condition' (whose value must be true or false)
has the value 'true'. The more elaborate form 

		if condition then
			statements
		else
			other_statements
		end if;

executes the enclosed 'other_statements' if the 'condition' has the value 'false'.

The still more elaborate form 

		if condition then
			statements
		elseif other_condition  then
			other_statements		
		else
			still_other_statements		
		end if;
		
tests a second 'other_condition' if 'condition' fails. This can have any number of 
'elseif' clauses, and can omit the 'else' clause.

<while>
while xxx loop	--

end loop;

<HELP>
The 'while' statement 

	while condition loop
		statements
	end loop;

executes the enclosed 'statements' as long as 'condition' (which is tested at the start of each iteration) is true.

<until>
until xxx loop	--

end loop;

<HELP>
The 'until' statement 

	until condition loop
		statements
	end loop;

executes the enclosed 'statements' until 'condition' (which is tested at the start of each iteration) becomes false.

<forin>
for xxx in xxx | xxx loop	--

end loop;

<HELP>
The 'for' iterator has three possible forms. Its first form is 

	for x in v | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a set, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be.

The second form of the 'for' iterator is 

	for x = f(j) | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a map, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range element f(j). j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 
j := 

The a third possible form of the 'for' iterator is 

	for x = f{j} | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each element j in the domain of f,
which must be a map. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range sets f{j}. j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 

		j := ...
<for=f()>
for xxx = xxx(xxx) | xxx loop	--

end loop;

<HELP>
The 'for' iterator has three possible forms. Its first form is 

	for x in v | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a set, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be.

The second form of the 'for' iterator is 

	for x = f(j) | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a map, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range element f(j). j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 
j := 

The a third possible form of the 'for' iterator is 

	for x = f{j} | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each element j in the domain of f,
which must be a map. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range sets f{j}. j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 

		j := ...

<for=f{}>
for xxx = xxx{xxx} | xxx loop	--

end loop;

<HELP>
The 'for' iterator has three possible forms. Its first form is 

	for x in v | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a set, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be.

The second form of the 'for' iterator is 

	for x = f(j) | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a map, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range element f(j). j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 
j := 

The a third possible form of the 'for' iterator is 

	for x = f{j} | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each element j in the domain of f,
which must be a map. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range sets f{j}. j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 

		j := ...

end loop;

<HELP>
The 'for' iterator has three possible forms. Its first form is 

	for x in v | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a set, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be.

The second form of the 'for' iterator is 

	for x = f(j) | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each item or character in v,
which can be a map, tuple, or string. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range element f(j). j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 
j := 

The a third possible form of the 'for' iterator is 

	for x = f{j} | condition loop
		statements
	end loop;

This executes the enclosed 'statements' once for each element j in the domain of f,
which must be a map. Items not satisfying the 'condition' are bypassed, unless the 'suchthat' clause ('| condition') has been omitted, as it can be. As the iteration proceeds, the variable 'j' is set to the domain element corresponding to each successive range sets f{j}. j can be replaced by any expresssion which could appear on the left side of a SETL assignment statement 

		j := ...

end loop;

<continue;>
continue;

<HELP>
The statements

		continue; 			and 			exit;
		
are used within SETL loops to proceed immediately to the next iteration, and to exit the loop, respectively. 

<exit;>
exit;

<HELP>
The statements

		continue; 			and 			exit;
		
are used within SETL loops to proceed immediately to the next iteration, and to exit the loop, respectively. 

<case>
case xxx 		-- 

	when xxx =>	-- 

	when xxx =>	-- 

	otherwise =>	-- 
	
end case;

<HELP>
The 'case' statement can have one of two main forms. The first form is

	case expression 		
	
		when const_val, =>	
				statements
		when other_const_val, =>	
				other_statements		
		otherwise =>	-- 
				still_other_statements		
	end case;

The 'expression' is evaluated and compared to the const_vals which appear in the
when 'const_val, =>' clauses (These must all be distinct.) If any equality is
found, the corresponding 'statements', but only these, are executed. If no equality is
found, the 'still_other_statements' following the 'otherwise =>' clause are executed,
provided that this clause has not been omitted, if it can be.

The second form of 'case' statement is

	case 		
	
		when boolean_expression =>	
				statements
		when other_boolean_expression =>	
				other_statements		
		otherwise =>	-- 
				still_other_statements		
	end case;

The 'boolean_expressions' in this statement are evaluated until one of them is found to be true, and then the corresponding 'statements', but only these, are executed. If none of these 'boolean_expressions' is found  to be true, the 'still_other_statements' following the 'otherwise =>' clause are executed, provided that this clause has not been omitted, as it can be.

<case(form2)>
case  		-- 

	when xxx =>	-- 

	when xxx =>	-- 

	otherwise =>	-- 
	
end case;

<HELP>
The 'case' statement can have one of two main forms. The first form is

	case expression 		
	
		when const_val, =>	
				statements
		when other_const_val, =>	
				other_statements		
		otherwise =>	-- 
				still_other_statements		
	end case;

The 'expression' is evaluated and compared to the const_vals which appear in the
when 'const_val, =>' clauses (These must all be distinct.) If any equality is
found, the corresponding 'statements', but only these, are executed. If no equality is
found, the 'still_other_statements' following the 'otherwise =>' clause are executed,
provided that this clause has not been omitted, if it can be.

The second form of 'case' statement is

	case 		
	
		when boolean_expression =>	
				statements
		when other_boolean_expression =>	
				other_statements		
		otherwise =>	-- 
				still_other_statements		
	end case;

The 'boolean_expressions' in this statement are evaluated until one of them is found to be true, and then the corresponding 'statements', but only these, are executed. If none of these 'boolean_expressions' is found  to be true, the 'still_other_statements' following the 'otherwise =>' clause are executed, provided that this clause has not been omitted, as it can be.

<{ in }>
{xxx: xxx in xxx | }
<HELP>
Setformers like {n * n: n in s | n /= 0} form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write {n in s | n /= 0} or {n * n: n in s}.

<{ = f()}>
{xxx: xxx = xxx(xxx) | }
<HELP>
Setformers like {n * n: n in s | n /= 0} form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write {n in s | n /= 0} or {n * n: n in s}.

<{ = f{}}>
{xxx: xxx = xxx{xxx} | }
<HELP>
Setformers like {n * n: n in s | n /= 0} form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write {n in s | n /= 0} or {n * n: n in s}.

<[ in ]>
[xxx: xxx in xxx | ]
<HELP>
Tuple formers like [n * n: n in s | n /= 0] form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write [n in s | n /= 0] or [n * n: n in s].

<[ = f()]>
[xxx: xxx = xxx{xxx} | ]
<HELP>
Tuple formers like [n * n: n in s | n /= 0] form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write [n in s | n /= 0] or [n * n: n in s].

<[ = f{}]>
[xxx: xxx = xxx{xxx} | ]
<HELP>
Tuple formers like [n * n: n in s | n /= 0] form the finite sets which they describe in a notation close to that of standard mathematics. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such setformers. Various elisions are possible if they cause no ambiguity, e.g. one can write [n in s | n /= 0] or [n * n: n in s].

<existsin>
(exists xxx in xxx | (xxx))
<HELP>
Existential quantifiers  like 

	exists n in s | n /= 0

test for the existence of the element which they describe in a notation close to that of standard mathematics, and if any such exists one is returned as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such existentials.

<exists=f()>
(exists xxx = xxx(xxx) | (xxx))
<HELP>
Existential quantifiers  like 

	exists n in s | n /= 0

test for the existence of the element which they describe in a notation close to that of standard mathematics, and if any such exists one is returned as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such existentials.

<exists=f{}>
(exists xxx = xxx{xxx} | (xxx))
<HELP>
Existential quantifiers  like 

	exists n in s | n /= 0

test for the existence of the element which they describe in a notation close to that of standard mathematics, and if any such exists one is returned as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such existentials.

<forallin>
(forall xxx in xxx | (xxx))
<HELP>
Universal quantifiers  like 

	for n in s | n /= 0

assert the truth of a condition, using a notation close to that of standard mathematics. If this is verifieed they return 'true'.  If not, they return 'false', and also return a counterexample as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such quantifiers.

<forall=f()>
(forall xxx = xxx(xxx) | (xxx))
<HELP>
Universal quantifiers  like 

	for n in s | n /= 0

assert the truth of a condition, using a notation close to that of standard mathematics. If this is verifieed they return 'true'.  If not, they return 'false', and also return a counterexample as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such quantifiers.

<forall=f{}>
(forall xxx = xxx{xxx} | (xxx))
<HELP>
Universal quantifiers  like 

	for n in s | n /= 0

assert the truth of a condition, using a notation close to that of standard mathematics. If this is verifieed they return 'true'.  If not, they return 'false', and also return a counterexample as the value of the existential's bound variable. Iterators, including nested iterators, of any of the forms acceptable in 'for' loops can appear in such quantifiers.

<lambda>
	procedure binder(param);		-- this returns a 'closure'
		return lambda(); return param; end lambda;
					-- this binds param into the parameterless function returned
	end binder;	

<HELP>
lambda blocks have the form 

	lambda(parameter,parameter,..); 		
		statements..
	end lambda;

They are nearly identical with procedure blocks, but have only parameters, not any name, since they are used to form 'anonymous' procedures, typically in contexts like 

	x := lambda(parameter,parameter,..); 		
		statements..
	end lambda;

which forms a procedure and assigns it to the value x. A simple example is 

		procedure bind_summand(n);
			return lambda(y); return y + n; end lambda;
		end bind_summand;
		
which when called forms a procedure into which the parameter value in is 'bound', so that for example the code

	p := bind_summand(222000); print(p(999));

prints the value 222999;

As this example shows, return statements can be used within lambda blocks. They have the form 

	return expn;				or 			return;

the latter equivalent to 'return OM;'

<null;>
null;

<HELP>
null statements  do nothing. They are used as syntactic filler where required, e.g. to be put in otherwise empty loops as surrogates for code still to be written;
<comments>
		--
		--

<HELP>
SETL comments are introduced by unquoted double minus signs, and run to the end of the line on which these signs appear. For example

	print("-- something");		-- what appears to the left is code, but this is just a comment
<print>
print(" ",xxx," ",xxx); 

<HELP>
print statements convert their sucessive arguments to strings and print them to SETL's standard output file or console. A newline is written after the final character printed by each print statement. To suppress this action, use 'nprint' instead.

<open>
xxx := open(xxx,"RANDOM");		-- or "TEXT-OUT", "TEXT-IN", "BINARY-OUT", "BINARY-IN", 

<HELP>
The statement 

	file_handle := open(file_name,"RANDOM");

converts the string name of a file into the 'handle' needed by other operations to reference the file. Other possibilities are 

	open(file_name,"TEXT-OUT");
	open(file_name,"TEXT-IN");
	open(file_name,"BINARY-OUT");
	open(file_name,"BINARY-IN");

Files can be opened only once, and must exist to be opened in any mode but "text-out" or "binary-out". The mode in which a file is be opened constrains the operations which can be applied to it, e.g. a file opened as "text-in" or  "binary-in" cannot be written

Both the "text-out" and "binary-out" modes of file acess begin by erasing the file being opened; newly opened files are always positioned at their start.
<close>
close(xxx);

<HELP>
close(file_handle); closes the file referenced by file_handle, allowing it to be re-opened subsequently.
<fexists()>
fexists(xxx);
<HELP>
fexists(file_name) returns 'true' if the naed file exists, 'false' otherwise.
<fsize()>
fsize(xxx)
<HELP>
fsize(file_handle) returns the length in bytes of the file referenced by file_handle.
<nprint>
nprint(xxx," ",xxx);  

<HELP>
nprint statements convert their sucessive arguments to strings and print them to SETL's standard output file or console. No newline is written after the final character printed.
<read>
read(xxx);  

<HELP>
read(x,y); statements read one complete SETL object from the standard input file or console for each of its (variable number of) arguments, and assigns it to this argument. It generates an error it it encounters a quantity which is not the legal print form of a SETL object.   

<reads>
reads(xxx,xxx,xxx); 
<HELP>
reads(stg,x,y); statements read one complete SETL object from the string s for each of its (variable number of) arguments, and assigns it to this argument. It generates an error it it encounters a quantity which is not the legal print form of a SETL object. The porion read is removed from s.   

<get>
get(xxx,xxx);
<HELP>
get(x,y); statements read one line from the standard input file or console for each of their (variable number of) arguments, and assigns the string read to this argument.

<geta>
geta(xxx,xxx,xxx);

<HELP>
geta(file_handle,x,y); statements read one line from the file referenced by file_handle for each of their (variable number of) arguments, and assigns the string read to this argument.

<gets>
gets(xxx,xxx,xxx,xxx);

<HELP>
gets(file_handle,start,n,x); statements read a string of length n from the file referenced by file_handle, starting at character 'start', and assigns the string read to x. The file must have been opened as "random" for this operation to be used.

<puts>
puts(xxx,xxx,xxx);

<HELP>
puts(file_handle,start,stg); statements writes the string 'stg' to the file referenced by file_handle, starting at character 'start'. The file, which is enlarged as much as necessary, must have been opened as "random" for this operation to be used.

<printa>
printa(xxx,xxx," ",xxx);  

<HELP>
printa(file_handle,x,y) statements convert their sucessive arguments (other than the first) to strings and print them to the file represented by 'file_handle'. A newline is written after the final character printed. To suppress this action, use 'nprinta' instead.

<nprinta>
nprinta(xxx,xxx," ",xxx);  

<HELP>
nprinta(file_handle,x,y) statement converts their sucessive arguments (other than the first) to strings and print them to the file represented by 'file_handle', without writing a newline after the final character printed.

<reada>
reada(xxx,xxx,xxx);  

<HELP>
reada(file_handle,x,y); statements read one complete SETL object from the file represented by 'file_handle' for each of their (variable number of) arguments, and assign it to this argument. It generates an error it it encounters a quantity which is not the legal print form of a SETL object.   

<eof()>
eof() 
<HELP>
The parameterless function eof() returns true if the last input statement executed encountered an end of file; false otherwise.

<abend_trap>
abend_trap := xxx;

<HELP>
If a value (which must be a parameterless procedure) has been supplied for the special variable 'abend_trap', it will be executed when and if its enveloping SETL program has generated an error, replacing the automatic abort which would otherwise take place. Aside from the fact that it is impossible to return from this 'customized abend' routine it behaves as a normal (but forced) procedure call,  within  which further abend_traps are possible and behave in the same  way. This makes it  possible to program a limited form of 'psuedo return': for an example of this, see the 'debug_watch' help item in the 'tools' section of this help facility.  (Since each such trap wil current print an abort message a few lines long, abend_trap routines should be written carefully to avoid an endless flood of output).

Often, however, the abend routine  used will simply print some final diagnostic imformation and then stop. An example of such rudimentary use is 

	program test;		-- illustration of the use of 'abend_trap'
	var step;
	
	abend_trap := lambda(); print("An error accured during step: ",step); stop; end lambda;

	step := 1; x := 0;
	step := 2; x +:= "some string";
		
	end test;
	
<stop>
stop;

<HELP>
The stop; statement terminates SETL execution immediately. 
	
<assert>
assert(xxx);

<HELP>
The assert(expn) statement, most commonly used during debugging,  asserts that its argument expression evaluates to true, and othrwise can stop execution. It operates in one of three way, depending on a preference setting: (i) assertions can be skipped altogether, tested with failed assertons stopping the program, or logged if successful, with failed assertons stopping the program. 
 
<sel>
sel xxx(xxx),xxx(xxx);

<HELP>
A declaration like

	sel x(1),y(2),z(3); 

defines the names which appear in it as synonyms for the tuple components selected by the numbers that the statement associates with them, and then allows C-like 'field' syntax, e.g. 
t.x, t.y, etc. to be used as a synonym for t(1), t(2) etc., in both 'evaluating' and 'assigning' positions. For example,  

	t := []; t.x := 22; print(t.x);

prints 22.

<OM>
OM
<HELP>
OM is the standard SETL 'undefined' quantity.

<numerics>
 1_000_000
<HELP>
Integer numerics can either be written in standard decimal format, e.g. 999999, or to any base n in the format n#xxxx.., as for example the hexadecimal 16#1234567890abcdef, or the binary 2#101101111. Underscores are allowed as punctuation marks in numerics, e.g we can write this same three quantities as 999_999, 16#1_234_567_890_abc_def, and 2#101_101_111. Floating point quantites can be written either standard decimal or in scientific notation, and to any base, as e.g. 1.5, 1.5E10, 1.5E-10, 2#1.01101111E8.  

<special_chars>
 "\n\x00"
<HELP>
 The special characters which have SETL 'escape' representations within quoted strings are " (which is "\""), \ (which is "\\"), \n (newline), \r (carriage return), \t (tab) \0 (zero bytes), and \f (form feed). Any characre can be represented as \xff in terms of its hexadecimal code. The char(n) function maps each integer in the range 0..255 into the character with numeric code n, and abs(c) maps in the other direction, so we have abs(char(n)) = n for all in the range 0..255, and "\xff" = char(16#xy) for all letters x,y in the hexadecimal range 0..f.
<arb>
arb xxx
<HELP>
The arb operator (which is monadic) returns an arbitrary element of the set or tuple x, or OM if this is empty.

<domain>
domain xxx
<HELP>
domain x returns the domain of x, which must be a map. 

<range>
range xxx
<HELP>
range x returns the range of x, which must be a map. 

<from>
xxx from xxx;

<HELP>
x from t; removes the last element from the tuple t, or any element of t if t is a set, and assigns it to x. x becomes OM if t is empty. x can be any expression which can appear to the left of an assignment operator; t can be any expression which can appear to the left or right of  an assignment operator.

<fromb>
xxx fromb xxx;

<HELP>
x fromb t; removes the first element from the tuple t and assigns it to x. x becomes OM if t is empty. x can be any expression which can appear to the left of an assignment operator; t can be any expression which can appear to the left or right of  an assignment operator.

<frome>
xxx frome xxx;

<HELP>
x frome t; removes the last element from the tuple t and assigns it to x. x becomes OM if t is empty. x can be any expression which can appear to the left of an assignment operator; t can be any expression which can appear to the left or right of  an assignment operator.

<not>
not xxx
<HELP>
not x is the negation of the boolean quantity x, i.e. is true if x is false, false if x is true.

<and>
xxx and xxx
<HELP>
x and y is the conjunction of the boolean quantities x and y, i.e. is true if both are true, otherwise false.

<or>
xxx or xxx
<HELP>
x or y is the disjunction of the boolean quantities x and y, i.e. is true if either is true, otherwise false..

<min>
xxx min xxx
<HELP>
x min y is the minimum of the (integer or real) quantities x and y.

<max>
xxx max xxx
<HELP>
x max y is the maximum of the (integer or real) quantities x and y.

<SECTION=Functs>
<cos()>
cos(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<sin()>
sin(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<tan()>
tan(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<acos()>
acos(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<asin()>
asin(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<atan()>
atan(xxx)
<HELP>
SETL provides the standard trigonometric functions sin, cos, tan, asin, acos, and atan.

<atan2>
atan2(xxx,xxx)
<HELP>
The  function atan2(x,y) returns the inverse tangent of the quotient of the two real quantities x and y.

<log(xxx)>
log(xxx)
<HELP>
SETL provides the standard (base e) exponential and logaritmic functions exp and log.

<exp()>
exp(xxx)
<HELP>
SETL provides the standard (base e) exponential and logaritmic functions exp and log.

<sqrt()>
sqrt()
<HELP>
sqrt(x) returns the square root of the real quantity x.

<tanh()>
tanh(xxx)
<HELP>
tanh(x) returns the hypebolic tangent of the real quantity x.

<str()>
str(xxx)
<HELP>
The str(x) function maps any SETL value to its string representation.

<unstr()>
unstr(xxx)
<HELP>
The unstr(x) function reads and the print form of a SETL value and returns the value (except in some ambiguous cases.) The binstr/unbinstr operations can be used instead of str/unstr to avoid these ambiguities.

<binstr()>
binstr(xxx)
<HELP>
The binstr(x) function maps any SETL value to a special binary string representation from which x can be reconstructed unambiguously using 'unbinstr'. That is, unbinstr(binstr(x)) is always x. The only exceptions are for values x involving atoms or procedures; these may not be reconstructible in subseqent runs, when atoms can be renumbered, or after recompilation of procedures written by the binstr operator. See the fuller SETL documentation for a more detailed discussion of this point.

<unbinstr()>
unbinstr(xxx)
<HELP>
The binstr(x) function maps any SETL value to a special binary string representation from which x can be reconstructed unambiguously using 'unbinstr'. That is, unbinstr(binstr(x)) is always x. The only exceptions are for values x involving atoms or procedures; these may not be reconstructible in subseqent runs, when atoms can be renumbered, or after recompilation of procedures written by the binstr operator. See the fuller SETL documentation for a more detailed discussion of this point.

<char()>
char(xxx)
<HELP>
The char(n) function maps each integer in the range 0..255 into the character with numeric code n, and abs(c) maps in the other direction, so we have abs(char(n)) = n for all in the range 0..255.

<newat()>
newat()
<HELP>
The parameterless newat() function generates a new SETL atom each time it is called.

<with>
xxx with xxx
<HELP>
s with x returns a set or tuple, otherwise identical to s, to which x has been added. If s is a tuple, x is added at the end.

<less>
xxx less xxx
<HELP>
s less x returns a set, otherwise identical to s, from which x has been removed.

<lessf>
xxx lessf xxx
<HELP>
f lessf x returns a map, otherwise identical to f, from which all pairs starting with x have been removed.

<mod>
xxx mod xxx
<HELP>
n mod m is the remainder of the integer n modulo m.

<pow>
pow xxx 
<HELP>
pow s returns the set of all subsets of s

<npow>
xxx npow xxx
<HELP>
's npow n' and 'n npow s' both return the set of all subsets of s containing exactly n elements.
 
<time()>
time()
<HELP>
The parameterless functions time() and date() produce stings representing the current time and date, as e.g. 19:20:34, 12/15/98.
 
<date()>
date()
<HELP>
The parameterless functions time() and date() produce stings representing the current time and date, as e.g. 19:20:34, 12/15/98.
 
<float()>
float(xxx)
<HELP>
float(x) converts the integer value x to a real quantity, rounding it to the available precision if necessary.

<abs()>
abs(xxx)
<HELP>
abs(x) returns the absolute value of the integer or real quantity x. If x is a single character, abs(x) returns its hexadecimal code, as an integer between 0 and 255.

<floor()>
floor(xxx)
<HELP>
floor(x) converts the floating point value x to the nearest integer that is no larger.

<ceil()>
ceil(xxx)
<HELP>
ceil(x) converts the floating point value x to the nearest integer that is no smaller.

<fix()>
fix(xxx)
<HELP>
fix(x) converts the floating point value x to the nearest integer.

<sign()>
sign(xxx)
<HELP>
sign(x) returns the sign of the real or integer quantity x, as 1 or -1.

<even()>
even(xxx)
<HELP>
even(x) returns the Boolean value 'true' if the integer x is even, false otherwise.

<odd()>
odd(xxx)
<HELP>
odd(x) returns the Boolean value 'true' if the integer x is odd, false otherwise.

<type()>
type(xxx)
<HELP>
The type(x) function maps each SETL value x into a capitalized string representing its type, e.g. ATOM, REAL, SET, BOOLEAN, STRING, TUPLE, INTEGER, PROCEDURE.

<is_atom()>
is_atom(xxx)
<HELP>
is_atom(x) returns the Boolean value 'true' if x is an atom, false otherwise.

<is_real()>
is_real(xxx)
<HELP>
is_real(x) returns the Boolean value 'true' if x is a real number, false otherwise.

<is_set()>
is_set(xxx)
<HELP>
is_set(x) returns the Boolean value 'true' if x is a set, false otherwise.

<is_map()>
is_map(xxx)
<HELP>
is_map(x) returns the Boolean value 'true' if x is a set all of whose elements are tuples of length 2, false otherwise.

<is_boolean()>
is_boolean(xxx)
<HELP>
is_boolean(x) returns the Boolean value 'true' if x is a boolean quantity, false otherwise.

<is_string()>
is_string(xxx)
<HELP>
is_string(x) returns the Boolean value 'true' if x is a string, false otherwise.

<is_tuple()>
is_tuple(xxx)
<HELP>
is_tuple(x) returns the Boolean value 'true' if x is a tuple, false otherwise.

<is_integer()>
is_integer(xxx)
<HELP>
is_integer(x) returns the Boolean value 'true' if x is an integer, false otherwise.

<is_procedure()>
is_procedure(xxx)
<HELP>
is_procedure(x) returns the Boolean value 'true' if x is a procedure, false otherwise.

<len>
len(xxx,xxx)
<HELP>
The function len(stg,n) removes and returns the first n characters of stg, or the whole of stg if stg is less than n characters long.

<any>
any(xxx,xxx)
<HELP>
The function any(stg,pat_stg) removes and returns the first character of stg if it belongs to pat_stg; otherwise it returns a null string and leaves stg unmodified. 

<notany>
notany(xxx,xxx)
<HELP>
The function notany(stg,pat_stg) removes and returns the first character of stg if it does not belong to pat_stg; otherwise it returns a null string and leaves stg unmodified. 

<span>
span(xxx,xxx)
<HELP>
The function span(stg,pat_stg) removes and returns the longest initial run of characters of stg all of whose characters belong to pat_stg. If there are none such it returns a null string and leaves stg unmodified. 

<break>
break(xxx,xxx)
<HELP>
The function break(stg,pat_stg) removes and returns the longest initial run of characters of stg none of whose characters belong to pat_stg. If there are none such it returns a null string and leaves stg unmodified. 

<match>
match(xxx,xxx)
<HELP>
The function match(stg,pat_stg) removes an initial segment of stg if it matches pat_stg exactly. Otherwise it returns a null string and leaves stg unmodified. 

<lpad>
lpad(xxx,xxx)
<HELP>
The function lpad(stg,n) pads stg on the left with blanks to make it n characters long. if stg is already longer than n characters it is unmodified. 

<rlen>
rlen(xxx,xxx)
<HELP>
The function rlen(stg,n) removes and returns the last n characters of stg, or the whole of stg if stg is less than n characters long.

<rany>
rlen(xxx,xxx)
<HELP>
The function rany(stg,pat_stg) removes and returns the last character of stg if it belongs to pat_stg; otherwise it returns a null string and leaves stg unmodified. 

<rnotany>
rnotany(xxx,xxx)
<HELP>
The function rnotany(stg,pat_stg) removes and returns the last character of stg if it does not belong to pat_stg; otherwise it returns a null string and leaves stg unmodified. 

<rspan>
rspan(xxx,xxx)
<HELP>
The function rspan(stg,pat_stg) removes and returns the longest terminal run of characters of stg all of whose characters belong to pat_stg. If there are none such it returns a null string and leaves stg unmodified. 

<rbreak>
rbreak(xxx,xxx)
<HELP>
The function rbreak(stg,pat_stg) removes and returns the longest terminal run of characters of stg none of whose characters belong to pat_stg. If there are none such it returns a null string and leaves stg unmodified. 

<rmatch>
rmatch(xxx,xxx)
<HELP>
The function rmatch(stg,pat_stg) removes a terminal segment of stg if it matches pat_stg exactly. Otherwise it returns a null string and leaves stg unmodified. 

<rpad>
rpad(xxx,xxx)
<HELP>
The function rpad(stg,n) pads stg on the right with blanks to make it n characters long. if stg is already longer than n characters it is unmodified. 

<SECTION=ClassPak>
<package>
package xxx; 		-- 
	procedure xxx(); 		-- 
	procedure xxx(); 		-- 

end xxx;

<HELP>
Package header blocks have the form 

	package pak_name; 		
		procedure name(parameter,parameter,); 		
		procedure other_name(parameter,parameter,); 		
			
	end pak_name;

Only procedure header lines, not their full bodies, are listed.  Package header blocks can contain declarations of their variables and constants, which are thereby made public for sharing between the subprocedures of a program which uses the package and all the subprocedures of the package.

Package body blocks have the form 

	package body name; 		

		procedure name(parameter,parameter,); 		
			more_statements
		end name;
	
		procedure other_name(parameter,parameter,); 		
			other_statements
	end name;

They obey the same syntactic and sematic rules as programs, but contain no 'main program block'.

<packagebody>
package body xxx; 		-- 

	procedure xxx(); 		-- 
	
		return zzz;
	end xxx;

	procedure xxx(); 		-- 
	
		return zzz;
	end xxx;

end xxx;

<HELP>
Package header blocks have the form 

	package pak_name; 		
		procedure name(parameter,parameter,); 		
		procedure other_name(parameter,parameter,); 		
			
	end pak_name;

Only procedure header lines, not their full bodies, are listed.  Package header blocks can contain declarations of their variables and constants, which are thereby made public for sharing between the subprocedures of a program which uses the package and all the subprocedures of the package.

Package body blocks have the form 

	package body name; 		

		procedure name(parameter,parameter,); 		
			more_statements
		end name;
	
		procedure other_name(parameter,parameter,); 		
			other_statements
	end name;

They obey the same syntactic and sematic rules as programs, but contain no 'main program block'.

<nativepackage>
native package xxx; 		-- 
	procedure xxx(); 		-- 
	procedure xxx(); 		-- 

end xxx;

<HELP>
Native package blocks  have the form 

	native package pak_name;
		procedure name(parameter,parameter,); 		
		procedure other_name(parameter,parameter,); 		
			
	end pak_name;

Only procedure header lines, not their full bodies, are listed. The native procedures referenced in such a block must be supplied in a C library included in a plugins folder contained in the same fodler as the SETL interpreter application. This library must have the form detailed in the full SETL reference document.

<class>
class xxx; 		-- 

end xxx;

<HELP>
Class header blocks and their associated class body blocks are used together to define new classes of SETL objects. Class header blocks have the form 

	class class_name; 		
		procedure name(parameter,parameter,..); 		
		procedure other_name(parameter,parameter,..); 		
			
	end class_name;

Only procedure header lines, not their full bodies, are listed.  Class header blocks can contain declarations of their variables and constants, which are thereby made public for sharing between the subprocedures of a program which uses the class and all the subprocedures of the class.
<class body>
class body xxx; 		-- 

end xxx;

<HELP>
Class body blocks and their associated class header blocks are used together to define new classes of SETL objects. Class body blocks have the form 

	class class_name; 		
		procedure name(parameter,parameter,..); 
			statements...
		end name;	

		procedure other_name(parameter,parameter,..); 		
			statements...
		end name;	
			
	end class_name;

The procedure definitions seen must include definitions of all the procedures listed in the associated class header.
 
Class bodies can also contain procedures with headers like 

		procedure self + x;		or 		procedure arb self;
		
which redefine built-in SETL operators for objects of the class. These use the keyword 'self' and are terminated by the single keyword 'end;'.

Class bodies can contain declarations of their variables and constants, which are thereby made privately available to all the procedures of the class and of other classes which inherit from it.
<classvar>
	class var xxx , xxx := xxx;

<HELP>
var (and const) declarations of several kinds can appear in classes and class bodies. Ordinary var declarations can appear at the start of a classes and class body. These declare 'instance variables', of which an individual copy is created for each subsequently created object obj of the class C. Instance variables x declared in the class (i.e. class header) are public, that is acessible (via the syntax obj.x) to all other programs, packages, and classes which use C.  Instance variables declared in the class body are private to C, that is, acessible only inside the procedures of C and of other classes which inherit from C.

var declarations of the modified form 

		class var x,..
		
declare 'class variables', of which only copy, created within the class itself, is shared by all subsequently created objects obj of the class. Class variables x declared in the class (i.e. class header) are public, that is acessible (via the syntax obj.x) to all other programs, packages, and classes which use C.  Class variables declared in the class body are private to C, that is, acessible only inside the procedures of C and of other classes which inherit from C.

The same rules apply to const declarations.
<create>
procedure create(xxx);		--

end create;

<HELP>
SETL objects of a class named class_name are created by calls of the form 

			obj := class_name(params..);

which use the name of their class as a fucntion name and which supply the paametrs (if any) reqired by the class' 'create' routine (if any has been supplied.) Space is allocated for this new object, all its instance variables are  given their desingnated initial values, and the new object is returned, by this statement itself, so no 'create' routine is actually required. However, if such a routine is supplied, it is called just before the newly created object is returned, snd so can be used to perform any additional initializations needed.

See the discussion of 'inherit' for an explanation of the way in which inherited parts of newly created objects can be initialized.
<self>
self
<HELP>
The keyword 'self' is used within the procedures of a class to designate the 'currently active'. When such a procedure p is invoked using the standard 'method' syntax obj.p(params..), 'self' refers to 'obj'; similarly for procedures with headers like

		procedure self + x;		or 		procedure self(x) := y;

when invoked by operations like obj + xx or obj(xx) := yy.

<self*>
procedure self * xxx;		--

	return zzz;
end;

<HELP>
All standard SETL binary operations, other than 'in' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self * xxx;				procedure xxx * self;
			statements...			or			statements...
		end;								end;

in the class' body. Both forms can be included together.

<*self>
procedure xxx * self;		--

	return zzz;
end;

<HELP>
All standard SETL binary operations, other than 'in' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self * xxx;				procedure xxx * self;
			statements...			or			statements...
		end;								end;

in the class' body. Both forms can be included together.

<self()>
procedure self(xxx);		--

	return zzz;
end;

<HELP>
The 'component retrieval' operation f(x) can be redefined for objects of a given class by including an operation definition of the form 

		procedure self(xxx);
			statements...
		end;

in the class' body.

<self():=>
procedure self(xxx) := yyy;		--

	return zzz;
end;

<HELP>
The 'component assignment' operation f(x) := y can be redefined for objects of a given class by including an operation definition of the form 

		procedure self(xxx) := yyy;
			statements...
		end;

in the class' body.

<self{}>
procedure self{xxx};		--

	return zzz;
end;

<HELP>
The 'set image retrieval' operation f{x} can be redefined for objects of a given class by including an operation definition of the form 

		procedure self{xxx};
			statements...
		end;

in the class' body.

<self{}:=>
procedure self{xxx} := yyy;		--

	return zzz;
end;

<HELP>
The 'set image assignment' operation f{x} := y can be redefined for objects of a given class by including an operation definition of the form 

		procedure self{xxx} := yyy;
			statements...
		end;

in the class' body.

<#self>
procedure #self;		--

	return zzz;
end;

<HELP>
The cardinality operation #x can be redefined for objects of a given class by including an operation definition of the form 

		procedure #self;
			statements...
		end;

in the class' body.

<-self>
procedure -self;		--

	return zzz;
end;

<HELP>
The negation operation -x can be redefined for objects of a given class by including an operation definition of the form 

		procedure -self;
			statements...
		end;

in the class' body.

<powself>
procedure pow self;		--

end;

<HELP>
The power set operation pow x can be redefined for objects of a given class by including an operation definition of the form 

		procedure pow self;
			statements...
		end;

in the class' body.

<notself>
procedure not self;		--

end;

<HELP>
The logical negation operation 'not x' can be redefined for objects of a given class by including an operation definition of the form 

		procedure not self;
			statements...
		end;

in the class' body.

<domainself>
procedure domain self;		--

end;

<HELP>
The domain operation 'domain x' can be redefined for objects of a given class by including an operation definition of the form 

		procedure domain self;
			statements...
		end;

in the class' body.

<rangeself>
procedure range self;		--

end;

<HELP>
The range operation 'range x' can be redefined for objects of a given class by including an operation definition of the form 

		procedure range self;
			statements...
		end;

in the class' body.

<self(i..)>
procedure self(xxx..);		--

end;

<HELP>
The tail slice retrieval operation t(i..) can be redefined for objects of a given class by including an operation definition of the form 

		procedure range self(xxx..);
			statements...
		end;

in the class' body.

<self(i..):=>
procedure self(xxx..) := yyy;		--

end;

<HELP>
The tail slice assignment operation t(i..) := y can be redefined for objects of a given class by including an operation definition of the form 

		procedure range self(xxx..) := yyy;
			statements...
		end;

in the class' body.

<self(i..j)>
procedure self(xxx..yyy);		--

end;

<HELP>
The slice retrieval operation t(i..j) can be redefined for objects of a given class by including an operation definition of the form 

		procedure range self(xxx..yyy);
			statements...
		end;

in the class' body.

<self(i..j}:=>
procedure self(xxx..yyy) := zzz;		--

end;

<HELP>
The slice assignment operation t(i..j) := y can be redefined for objects of a given class by including an operation definition of the form 

		procedure range self(xxx..yyy) := zzz;
			statements...
		end;

in the class' body.

<fromself>
procedure from self;		--

end;

<HELP>
The extraction operation 'from x' can be redefined for objects of a given class by including an operation definition of the form 

		procedure from self;
			statements...
		end;

in the class' body. The same applies to the operations 'fromb' and frome'.

<inself(iter)>
procedure iterator_start;		--

end iterator_start;

procedure iterator_next;		--

end iterator_next;

<HELP>
SETL iterators of the form .. x in obj .. can be redefined for objects of a given class by including a pair of parameterless procedures

		procedure iterator_start;				procedure iterator_next;
			statements...			and				statements...
		end iterator_start;						end iterator_next;

in the class' body. The iterator_start routine will be called as the iteration is entered, and should initialize whatever internal data objects are needed for the iteration. The iterator_next routine will be called once for each iteration cycle, and should return a singleton tuple whose one component is the next 'supbart' of obj to be returned by the iteration .. x in obj .. To terminate iteration, the value OM should be returned instead of a singleton tuple.

SETL iterators of the form .. x = obj(y) .. are treated as synonyms for iterators

				 .. [x,y] in obj ..

and so can be redefined for objects in the same way.

<=self{}>
procedure set_iterator_start;		--

end set_iterator_start;

procedure set_iterator_next;		--

end set_iterator_next;

<HELP>
SETL iterators of the form .. x = obj{y} .. can be redefined for objects of a given class by including a pair of parameterless procedures

		procedure set_iterator_start;				procedure set_iterator_next;
			statements...				and				statements...
		end set_iterator_start;						end set_iterator_next;

in the class' body. The set_iterator_start routine will be called as the iteration is entered, and should initialize whatever internal data objects are needed for the iteration. The set_iterator_next routine will be called once for each iteration cycle, and should return a singleton tuple whose one component is the pair [x,y] of values to be returned by the iteration .. x = obj{y} .. To terminate iteration, the value OM should be returned instead of a singleton tuple.

<selfstr>
procedure selfstr(xxx);		--

end;

<HELP>
The built-in function 'str(x)', which produces a SETL object's string form, can be redefined for objects of a given class by including a parameterless operation definition of the form 

		procedure selfstr;
			statements...
		end;

in the class' body. Since this function is used by the functions 'print' and 'printa' to convert objects to strings, this defintion will also control the way in which objects of the class print.

<selfand>
procedure self and xxx;		--

end;

<HELP>
The SETL logical binary operations 'and' and 'or' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self and xxx;				procedure xxx and self;
			statements...			or			statements...
		end;								end;

in the class' body. Both forms can be included together.

<selfnpow>
procedure self npow xxx;		--

end;

<HELP>
The SETL binary powerset operation 'npow' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self npow xxx;			procedure xxx npow self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<selfwith>
procedure self with xxx;		--

end;

<HELP>
The SETL binary operations 'with', 'less', and 'lessf' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self with xxx;			procedure xxx with self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<selfless>
procedure self less xxx;		--

end;

<HELP>
The SETL binary powerset operations 'with', 'less', and 'lessf' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self less xxx;			procedure xxx less self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<selflessf>
procedure self lessf xxx;		--

end;

<HELP>
The SETL binary powerset operations 'with', 'less', and 'lessf' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self less lessf;			procedure xxx lessf self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<selfmod>
procedure self mod xxx;		--

end;

<HELP>
The SETL operations 'mod'can be redefined for objects of a given class by including an operation definition of the form 

		procedure self mod lessf;			procedure xxx mod self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<selfmax>
procedure self max xxx;		--

end;

<HELP>
The SETL binary operations 'max' and 'min' can be redefined for objects of a given class by including an operation definition of the form 

		procedure self max lessf;			procedure xxx max self;
			statements...			or			statements...
		end;								end;

in the class' body.  Both forms can be included together.

<inherit>
inherit xxx,xxx;

<HELP>
Any SETL class C can be declared to inherit part of its structure form a list of previously defined classes C',C''... This is done by including one or more declarations of the form

		inherit C',C'',...; 

at the start of C's class definition (i.e. header block). This causes a copy of every instance and class variable of C', C'',... to be incorporated into every object of type C, and (if there are no name conflicts) to be available to such objects under their original names. Similarly every method defined for objects of type C', C'' becomes available to objects of class C under its original names (again provided that there are no name conflicts.)

The definition of any constant, variable or procedure in any of C', C'',... can be over-ridden in C by defining a constant, variable or procedure having the same name. Aside from this, if any two of C', C''.. define conflicting constants, variables or procedures having the same name 'name', then this name becomes unavailable to objects of type C. Howerer, reference to the constants, variables or procedures are still possible by using the name in an explicitly qualified form like C'.name or C''.name.

<Dynamic evaluation>
program test;
	print(x := 1); eval("print(x := 2 + 2);"); print(x);
end;
<HELP>
SETL's dynamic evaluation facility allows arbitrary strings representing the body of any program to be  compiled and executed  dynamically. The argument submitted to this function should be a string representing any valid SETL program (but without the normal 'program ..' and 'end..' header and trailer line. 

Programs and packages can be compiled statically by including them in the same kind of source string. Code successfully compiled in this way is written to the currently active SETL library; see below. This code over-writes any prior library programs and packages having the same names. The static name scoping rules described in the SETL manual apply to such code. 

Strings passed to 'eval' in this way are compiled into an auxiliary in-RAM SETL library and then executed immediately. 'eval' returns the value OM if its argument is syntactically ill-formed, otherwise 0. 

The following name scoping rules relate statically compiled and dynamically evaluated code. 

Names used in dynamically compiled code have scopes entirely distinct from those appearing in statically compiled code libraries, except that names declared in statically compiled classes and packages and then used in dynamically compiled code take on meanings common to both. To see this, try 

	print(x := 1); eval("print(x := 2);"); print(x); 

The third statement prints the same value 1 as the first statement since the 'x' in the dynamically compiled statement is distinct from that in the first and third statements, which are statically compiled. 

However, names declared in statically compiled classes and packages which are then used in dynamically compiled code retain their original meanings, try 

		eval("use string_utility_pak; print(upper_case_letters);"); 

and then 

eval("use string_utility_pak; print(str(breakup(breakup(\"1.22.333.4444.55555; a.b.c.d;AA.BB.CC.DD\",\";\"),\".\")));"); 

The fact that names declared in statically compiled packages which are used in dynamically compiled code gives us a way of passing values back and forth between
statically compiled and dynamically evaluated code. To see this, try 

package share_names; var xs,ys; end share_names;

and then 

program test; use share_names; 
        xs := 1; eval("use share_names; print(xs); ys := 2;"); 
        print(ys);
end test;

Since the names xs and ys are declared in the package 'share_names' which both the static and the dynamic parts of the code use, these names are common to both kinds
of code; so the dynamic code prints the value 1 assigned by the static code, and the static code prints the value 2 assigned by the dynamic code. 

Since SETL treats procedures as first-class values, this gives us a way of passing dynamically created procedures back into static code. The following example illustrates
this: 

program test; use share_names; 
        stg := "use share_names; ys := print_a_sum;";
        eval(stg +  
      "procedure print_a_sum(x); print(x + 999); return x; end print_a_sum;"); 
        print(ys(11));
end test;

In this example, the procedure 'print_a_sum', which adds 999 to its argument and prints the result, is formed within the dynamic code and passed back to the static code.
This invokes it with the parameter 11,causing 1010 to be printed 

As the preceding example indicates, dynamically evaluated code can contain procedure bodies and so can form procedures. Names appearing within such procedures are
local to the procedures, and so are distinct both from all names in static code and all top-level names in dynamic code, unless they appear in top-level declarations (which
lie inside the dynamic code) of the form 

        var name_1,name_2,...;  or      const name_1,name_2,...;

in which case the are identified with the corresponding top-level names. The example 

        eval("var x; x := 1; y := 2; p(); procedure p; print(x,\" \",y); end p;");

shows the effect of this rule. Since x is 'globalized' by a 'var' statement, the procedure p prints it as a 1; since y is not, it has no value within p and prints as OM. 

Names used at the top level within several successive 'eval' statements within a single SETL run retain a constant meaning. Try print(x := 1); eval("print(x := 2);");
print(x); eval("print(x);"); to see this. Again, the third statement prints the same value 1 as the first statement, but now the second and fourth statements both print 2, since
the 'x' in the dynamically compiled statements are both the same, but distinct from that in the first and third statements, which are statically compiled. 

On the other hand, names lose their meaning between distinct SETL runs, since each of these involves a separate invocation of the SETL interpreter by Netscape. To see
this, try print(x := 1); eval("print(x := 2);"); print(x); eval("print(x);"); again, and then immediately print(x); eval("print(x);");. Both x's print as the SETL undefined value
OM, since both lose their value when the first SETL run ends and the second begins. 

To avoid this effect, one can simply use a SETL 'listener' which enters a read/eval loop, reading and evaluating successive statement blocks, including any statements
which they may contain. Such a 'listener' program is invoked by the 'Evaluate' button seen in the bottom frame. For the moment, this is getting its input from a simple
prompt dialog window which it opens. Semicolon-separated sequences of statements can be entered into the dialog. This sequence of statements can end with an
expression (which should not be followed by a semicolon.) If it does, the value of this final expression will be printed. Try entering x := 2 and then immediately
afterwards x to see how this works; then try y := 3; x := 2 and immediately afterwards x + y. 

As noted above, dynamic evaluations can make use of procedures and constants declared in statically compiled classes and packages. The code executed by the 'Evaluate'
button makes use of this fact by prefixing the string which it evaluates by a 'use' statement containing all the package names entered into the input area immediately to its
left. Try this by entering 'string_utility_pak' into that area, and then using the 'Evaluate' button to evaluate breakup("a.bb.cc!ddd",".!"). Or enter 'rational' and then
Evaluate (x := rational(1,3)) + (y := rational(1,6)) followed immediately by x * y. 

<Dynamic package loading>
program test;
	print(library_package("RANDOM_PAK"));
end test;
<HELP>
The built-in SETL function library_package can be used to load all the procedures of any precompiled SETL package. The package name should be passed as an upper-case string. 'library_package' returns a mapping of each (upper-case) name of a procedure in the package to a procedure value identical with the procedure name. Repeated calls to 'library_package' check for packages already loaded and do not load them a second time, even if they have  been (dynamically) recompiled in the mean while (see 'Dynamic compilation'.)

 Drag in the example provided by the 'Dynamic package loading' header line seen above, which will show what is meant.

Note also that 'library_package' recursively loads all the packages and classes required by any package or class which it loads.

<Dynamic compilation>
program test;
	use parser;

	compile("package test_pak; procedure test_proc(x); end;" + 
	"package body test_pak; procedure test_proc(x); return x * x; end test_proc; end test_pak;");
	tp := library_package("TEST_PAK")("TEST_PROC");
	print(tp(3));			-- prints 9

	compile("package test_pak; procedure test_proc(x); end;" + 
	"package body test_pak; procedure test_proc(x); return x * x; end test_proc; end test_pak;");
	tp := library_package("TEST_PAK")("TEST_PROC");
	print(tp(3));			-- prints 9

	compile("package test_pak2; procedure test_proc(x); end;" + 
	"package body test_pak2; procedure test_proc(x); return x * x * x; end test_proc; end test_pak2;");
	tp := library_package("TEST_PAK2")("TEST_PROC");
	print(tp(3));			-- prints 27

end test;
<HELP>
The native package 'parser' supplied with the SETL system provides two functions, 'parse' and 'compile', which make key portions of SETL's system-level compilation capability available to  SETL programs. 'compile(stg)', which can be  applied to any string representing a syntactically valid combination of SETL programs, packages, and classes,  compiles this string into the currently active SETL library (see below.) if 'stg' is not syntactically valid, 'compile(stg)' returns OM, otherwise 0 is returned. 

Used in combination with SETL's built-in 'library_package' function, 'compile(stg)' gives  SETL a useful compile-load-execute capability. Note however that once loaded into the SETL environment, a package  will not be reloaded if recompiled unless either its name is changed or the SETL program executing is fully reloaded using SETL's dynamic re-execution capability. Drag in the example provided by the 'Dynamic compilation' header line seen above, which will show what is meant. 

<Dynamic re-execution>
program testit;
	use ide_pak,parser;	-- the first of  these supplies 'ide_rerun',  the second supplies 'compile'
	
	print("command_line is: ",command_line);
	if (command_line = []) then
		ide_rerun("Longword");
	elseif (word1 := command_line(1)) = "L" then
		compile("program testit; print(\"Recompiled version: \",command_line,\" \",99999 + 99999); end testit;");
		ide_rerun("Longword");
	elseif word1 = "Long" then
		ide_rerun(word1(1..#word1 - 1));
		abort("Aborting"); print("After abort"); 
	else 
		ide_rerun(word1(1..#word1 - 1));
		print("Before stop"); stop; print("After stop"); 
	end if;

end testit;
<HELP>
The native package 'ide_pak' supplied with the SETL system provides a function ide_rerun(stg) which, if called, will cause the currently executing program to re-execute, (possibly in a re-compiled form, if the program has recompiled itself using the 'compile' operation  described in the 'Dynamic compilation' help item.) Re-execution is triggered when the initial run either finishes normally,  stops, or aborts. The string-valued parameter of ide_rerun(stg) is passed to the new run as the value of the built-in 'command_line' variable. (More precisely, command_line becomes the tuple of all blank-seaprated  words in 'stg'.) 

<SECTION=Widgets>
<template>
program test;	-- standard template for interactive programs
use tkw,string_utility_pak;		-- use the main widget class

var Tk,global_1,global_2,global_3;

	Tk := tkw(); Tk(OM) := "Caption";						-- create the Tk interpreter
	
			-- widgets can be put into a frame, or directly into Tk
	parent := Tk("frame","100,50"); parent("side") := "top"; 
	parent("background") := "#aaaaaa";	-- grey background
	
	parent2 := Tk("frame","100,50"); parent2("side") := "top"; 
	parent2("background") := "#cccccc";	-- lighter grey background
	
			-- *** create all the other interface widgets by inserting code here *** 
			
	Tk.mainloop();		-- enter the Tk main loop

	procedure my_procedure();	-- procedures go here
		
	end my_procedure;

end test;

<HELP>
This is a standard template for starting to develop interactive programs.
<toplevel>

toplev := parent("toplevel","100,100");		-- giving initial height and width
toplev(OM) := "Caption";

<HELP>
Attributes are: height, width, background, cursor, borderwidth, highlightbackground,
highlightcolor, highlightthickness, menu, relief, takefocus, screen, visual 

'toplevel' widgets are self-standing windows of whatever kinds are available. They are created by a command of the form 

	toplevel_name := tkw_name("toplevel","999,999");

where 'tkw_name' is the name of the master widget object. All other widgets are then created and arranged hierarchically within the toplevel' widgets opened.

Each toplevel can have its own menubar.

use				- modifier for create command: embeds window in pre-existing window????

The attributes of a toplevel are as follows:

		height, width			- window height and width 
		background				- window background color 
		cursor					- cursor to display when mouse is over window
		borderwidth				- width of border around window
		highlightbackground		- border color when window does not have focus
		highlightcolor			- border color when window does have focus
		highlightthickness		- window border thickness for hilighting 
		menu					- menu to use for menubar
		relief					- flat, sunken, raised, groove, or ridge
		takefocus				- see explanation found under the help keyword 'focus'
		
		screen					- screen on which toplevel is placed (XWindows only)
		visual					- color mapping to be used within window  (XWindows mainly)
								- see help item for 'visual'

<frame>

fr := parent("frame","100,100"); fr("side") := "top";	-- if packed; or left,right,bottom
fr("background") := "#ffaaaa";		-- for a pink background

<HELP>
Attributes are: height, width, background, cursor, borderwidth, highlightbackground,
highlightthickness, relief, takefocus

frames are rectangular areas within toplevel windows or other frames, within which other widgets can be arranged. They are created by commands of the form 

	xxx := parent_frame("frame");

Other widgets can then be created and arranged hierarchically within such frames.

The attributes of a frame are as follows:

		height, width			- frame height and width 
		background				- frame background color 
		cursor					- cursor to display when mouse is over frame
		borderwidth				- width of border around frame
		highlightbackground		- border color when frame does not have focus
		highlightcolor			- border color when frame does have focus
		highlightthickness		- frame border thickness for hilighting 
		relief					- flat, sunken, raised, groove, or ridge
		takefocus				- see explanation found under the help keyword 'focus'

<canvas>
ca := parent("canvas","300,100"); ca("side") := "left";	-- if packed; or left,right,bottom

<HELP> 
Attributes are: height, width, background, borderwidth, cursor, insertbackground, insertborderwidth, insertofftime, insertontime, highlightbackground, highlightcolor,highlightthickness, relief, coords, class, colormap, container, menu, screen, takefocus, use, visual, closenough, confine, selectbackground, selectforeground, selectborderwidth, xscrollincrement, yscrollincrement, scrollincrement, scrollregion 

Canvases are rectangular areas in which geometric shapes and other widgets can be draw at specified positions. The objects which can be drawn into a canvas are called 'canvas items'. The geometric objects allowed are  arc, bitmap, image, line, oval, polygon, text, and image. Additionally, any other widget, including canvases and frames, can drawn to a canvas, so that canvases can be structured as collages of basic geometric abjects and subcanvases.

Canvases can occupy rectangles larger than that in which they are displayed, in which case they can be scrolled.

Each type of canvas item has its own set of attributes. The attributes of a canvas itself are as follows:
 
		height, width			- canvas height and width 
		background				- canvas background color 
		borderwidth				- width of border around canvas
		cursor					- cursor to display when mouse is over canvas
		insertbackground		- color of insertion cursor
		insertborderwidth		- border width for insertion cursor, if displayed in relief
		insertofftime,insertontime	- blink times for insertion cursor
		highlightbackground		- border color when canvas does not have focus
		highlightcolor			- border color when canvas does have focus
		highlightthickness		- border thickness for hilighting 
		relief					- 3d relief of canvas border
		coords					- 
		class					- 
		colormap				- 
		container				- 
		menu					- 
		screen					- 
		takefocus				- see explanation found under the help keyword 'focus'
		use						- 
		visual					- 
		closenough				- 
		confine					- 
		selectbackground		- 
		selectforeground		- 
		selectborderwidth		- 
		xscroller				- horizontal scrollbar for the canvas, if any
		yscroller				- vertical scrollbar for the canvas, if any
		yscrollincrement		-
		scrollincrement			-
		scrollregion			-

<canvasitem>
rect := ca("rectangle","20,20,60,40"); rect("fill") := "red";
oval := ca("oval","80,20,120,40"); oval("width") := 5;
line := ca("line","140,20,180,20,180,40,20,40"); line("fill,smooth") := "blue,true";
poly := ca("polygon","140,60,180,60,180,100,20,100"); poly("fill,smooth") := "blue,true";

ct := ca("text","Text in the canvas"); 
ct("coords") := "30,30"; ct("anchor,font") := "nw,{Times 36}";	

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, and text. Additionally, any other widget, including canvases and frames, can drawn to a canvas, so that canvases can be structured as collages of basic geometric objects and subcanvases.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For rectangles, arcs and ovals, these are the left, top, right, bottom of the enclosing rectangle (in the case of arcs, the enclosing rectangle of the oval on which the arc lies.) For lines (open curves) and polygons (closed curves) these are the x and y coordinates of the controlling vertices (note that these curves can be splines.) For bitmaps, images, text, and  these are the x and y coordinates of the item's anchor point (e.g. center.) 

Each item can also have an associated list of tags, given by its "tags" attribute.

Each type of canvas item has its own set of additional attributes. These are listed in the folowing table:
	
	rectangle, oval: 
		width				- width of outline
		fill				- color for interior
		outline				- color for outline
		stipple				- pattern for interior

	arc: 
		style				- pieslice, chord, or arc (circular boundary only)
		start				- starting angle of circular arc, in degrees
		extent				- extent of circular arc, in degrees
		width				- width of outline
		fill				- color for interior
		outline				- color for outline
		stipple				- pattern for interior
		outlinestipple		- pattern for outline
	
	line: (open curve)
		width				- line width
		smooth				- if true, line is a spline curve 
		splinesteps			- number of intermediate smoothing points to use, if spline
		fill				- line color
		stipple				- line pattern
		joinstyle			- line corner join style: bevel, miter, or round
		capstyle			- line end style: butt, projecting, or round		
		arrow				- should arrowheads be drawn: none, first, last, or both
		arrowshape			- tuple [overall length, length from point to line end, width]	
	
	polygon: (closed curve)
		width				- polygon outline width
		smooth				- if true, polygon is a spline curve 
		splinesteps			- number of intermediate smoothing points to use, if spline
		fill				- color for polygon interior
		outline				- color for polygon outline
		stipple				- pattern for arc interior
	
	bitmap: 
		bitmap				- file name or built-in bitmap name defining picture geometry
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se
		background			- display color for bitmap background
		foreground			- display color for bitmap foreground
	
	image: 
		image				- image object to appear in canvas item
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se
	
	text: 
		text				- actual text string
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se
		font				- text font, e.g. "Times,20,bold"
		justify				- left, right, or center
		fill				- text color
		stipple				- text pattern
		width				- text area width 
	
	widget:
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se

<textwidget>
	txt := parent("text","10,10"); txt("side") := "left"; txt(OM) := "Type\ntext\nhere";
	print(txt("1.0".."2.1"));
	txt.tag_add("my_tag","1.1,1.1,2.1,3.3"); 
	txt("my_tag","font,background,foreground,justify") := "{times 24 bold italic},red,yellow,center";
	txt{"my_tag","Button-1"} := my_procedure;
	print(txt.tag_names(OM));			-- print ordered list of tags associated with widget

<HELP>
Text widgets 'tex' are editable multi-line text entry areas which support selection, hotwording and multifonting using  a ppowerful system of 'tags' and 'marks'.

The text in a textline widget can be manipulated using string-like syntax: tex(m..n) designates the characters in the range m thru n, tex(OM) all the text in the widget, #tex the number of characters of text. 

In the expression tex(m..n), m and n can either be strings of the form line.char (where, in the initial index m, the 'char' integeris 0-based), or one of the following constants, designating special positions in the text within the widget:

	@x,y			- the character at screen point x,y
	end				- last character
	insert			- position of insertion cursor
	tag_name.first	- first character in the range tagged by "tag"
	tag_name.last	- first character after the range tagged by "tag"
	mark_name		- first character after the indicated mark
	current			- the character under the mouse
	some_image		- character position of an embedded image
	some_widget		- character position of an embedded widget

These index expressions can be modified by the addition of the following suffixes:
 
	wordstart		- start of word containing character
	wordend			- start of word containing character
	linestart		- start of line containing character
	lineend			- start of line containing character
	+n				- n characters forward, same line (e.g. "current+15")
	-n				- n characters previous, same line
	+nlines			- n lines forward, same character position (e.g. "current+5lines")
	-nlines			- n lines previous, same line

'Tags' associated with a text widget designate (not necessarily contiguous) ranges within the text. 'Marks' designate single points within the text, which 'float' in  the text as insertions and deletions are  made. The special, built-in tag 'sel' denotes the currently selected range within a text widget's text.

The operations which add tags to and  delete tags from ranges in a text widget are respectively 

	textwidget.tag_add(tag,index_range_stg); and 
	textwidget.tag_remove(tag,index_range_stg);

Here 'index_range_stg' designates a comma-separated set of text indices in increasing order,  the pieces of the range  running from each odd-numbered postion to the next  following  even-numbered position (or  to the end  of the text.)

To bind callback procedures to textfield tag events we use the syntax 

	textwidget{"tag_name","event_descriptor,event_fields_signature"}
				 := SETL_procedure;
		
This is like all other binding syntax, but carries a tag name as an extra parameter.

The attributes of text widgets are:

		width, height			- widget horizontal and vertical dimensions
		state					- normal or disabled (if disabled, text is read-only)
		font					- text font
		padx,pady				- extra space around text, inside of border
		foreground				- text color
		background				- text background color
		justify					- left, right, or center
		wrap					- line wrap mode: none, char, or word
		selectbackground		- background color for selected text 
		selectforeground		- foreground color for selected text 
		selectborderwidth		- width of selection border (for 3D selection effect) 
		borderwidth				- extra space around edge of text
		cursor					- cursor to display when mouse is over canvas
		setgrid					- if true, height and width attributes are in character units
		spacing1				- extra space above each unwrapped line
		spacing2				- extra space interior to wrapped lines
		spacing3				- extra space below each unwrapped line
		tabs					- list of tab stops
		insertwidth				- width of insertion cursor
		insertbackground		- color of insertion cursor
		insertborderwidth		- border width for insertion cursor, if displayed in relief
		insertofftime,insertontime	- blink times for insertion cursor
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when widget does not have focus
		highlightcolor			- color of additional border when widget has focus
		relief					- flat, sunken, raised, groove, or ridge
		exportselection			- use XWindows selection export mechanism (XWindows only)
		takefocus				- see explanation found under the help keyword 'focus'
		xscroller				- horizontal scrollbar for the text widget, if any
		yscroller				- vertical scrollbar for the text widget, if any

Special operations available for text widgets are: 
<textitem>
**
<HELP>
text items are items other than character strings that can appear within text widgets. Two types of text item are provided: widget items and image items. When inserted, items of this kind are treated as if they were 'large characters'. Any widget can be inserted into text as a widget item. Besides their inherent attributes, widgets inserted in this way have the following special attributes:

		widget		- the widget to appear
		align		- alignment of widget in surroundig text: top, center, bottom, or baseline
		padx		- extra space at left and right of item
		pady		- extra space at top and bottom of item
		stretch		- if true, widget will stretch to match text layout
 
 Any absolute image can be inserted into text as a text item. Besides their inherent attributes, images inserted in this way have the following special attributes:

		image		- the image to appear
		align		- alignment of widget in surrounding text: top, center, bottom, or baseline
		padx		- extra space at left and right of item
		pady		- extra space at top and bottom of item
		name		- name for this image instance 
<tag>
**

<HELP>
Tags are used to mark ranges of text in text widgets, and sets of graphic items in canvases.

<focus>
for j in [1..5] loop 
	but := Tk("button","Click" + str(j)); but("side") := "left"; 
	but{OM} := setcolor(but); 
	but("takefocus") := lambda(but_name);  
				but := Tk.obj_from_tkname(but_name(1));
				but("foreground") := "blue"; return 1; 
			end lambda; 
end loop;
procedure setcolor(but); return lambda(); but("foreground") := "red"; end lambda; end setcolor;

<HELP>
The 'focus' can be passed among the widgets in a window by hitting the tab key. This moves the focus forward in the circular order of these widgets; hitting Shift-tab moves the focus backward in this circular order. The 'takefocus' attribute of widgets controls the way in which they react to the arrival of the focus. A widget whose 'takefocus' attribute is set to 0 will always pass the focus along in circular order when it arrives; a widget whose 'takefocus' attribute is set to 1 will always take the focus when it arrives, but do nothing else. The 'takefocus' attribute can also be set to a null string, in which case default rules, which in some cases reflect the state of the widgets the circular order of widgets, will decide whether each widget accepts the focus or passes it along. Finally, a SETL procedure FP can be assigned as the value of a widget's 'takefocus' attribute. This procedure will be called as soon as focus arrives at the widget, the Tk 'string name' of SN the widget will be passed to it. (The widget object itself can be recovered from this internal 'string name' by using the function Tk.obj_from_tkname(SN).) The procedure FP should return 0, 1, or a blank string, depending on whether the widget is to refuse the focus and pass it along to the next widget in circular order, or to take the focus, or to use the default rules mentioned above to make this decision. 

When a widget has the 'focus', the principal command (if any) associated with it can be executed by hitting the space bar. 

<textline>
tline := parent("entry",30); tline("side") := "left"; tline(OM) := "Type text here";

<HELP>
textline widgets 'texl' are editable single-line text entry areas. The text in a textline widget can be manipulated using string-like syntax: texl(m..n) designates characters m thru n, texl(OM) all the text in the widget, #texl the number of characters of text. In the expression texl(m..n), m and n can either be integers, or one of the following constants, designating special positions in the text within the widget:

	anchor			-- the index of the anchor point (left, right, or center) of the selection
	end				-- last character
	insert			-- position of insertion cursor
	sel.first		-- first selected character
	sel.last		-- last selected character
	
A negative integer -n can be used to designate the character at horizontal screen position n.

The attributes of textline widgets are:

		state					- normal or disabled (if disabled, text is read-only)
		font					- text font
		show					- character to display in place of contents
		foreground				- text color
		background				- text background color
		justify					- left, right, or center
		selectbackground		- background color for selected text 
		selectforeground		- foreground color for selected text 
		selectborderwidth		- width of selection border (for 3D selection effect) 
		borderwidth				- extra space around edge of text
		cursor					- cursor to display when mouse is over canvas
		insertwidth				- width of insertion cursor
		insertbackground		- color of insertion cursor
		insertborderwidth		- border width for insertion cursor, if displayed in relief
		insertofftime,insertontime	- blink times for insertion cursor
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when widget does not have focus
		highlightcolor			- color of additional border when widget has focus
		relief					- flat, sunken, raised, groove, or ridge
		exportselection			- use XWindows selection export mechanism (XWindows only)
		takefocus				- see explanation found under the help keyword 'focus'
		textvariable			- if non-null, names a Tk variable holding the widget's string

Special operations available for textline widgets are: 

	texl.bbox(n);			-- return bounding box of specified character
	texl.icursor_move(n);		-- move the inset cursor to position n
	texl.select(m,n);		-- select characters m to n, or clear the selection
	texl.is_select();		-- test if there is a selection
	texl.select_anchor(m);		-- set the anchor point for the selection???

	texl.xview(n);			-- scroll to make indicated character visible
	texl.xview_percent(p);	-- scroll to place fraction p of string offscreen to the left
	texl.xview_scroll(n,what);	-- scroll n 'units'
	texl.scan_to(x);		-- scroll to indicated position
	texl.scan_mark(x);		-- place mark indicating scroll position???
	texl.index(index_key);	-- get numerical value of index_key, e.g. anchor, end, insert, etc.

<button>
but := parent("button","Label"); but("side") := "left";
but{OM} := Tk.beeper;	-- or any other parameterless function
checkbut := parent("checkbutton","Label2"); checkbut("side") := "left";
radbut1 := parent("radiobutton","Radio1"); radbut1("side") := "left";
radbut2 := parent("radiobutton","Radio2"); radbut2("side") := "left";
radbut1("variable,value") := "x,r1"; radbut2("variable,value") := "x,r2";
-- the common 'variable' and distinct 'values' puts these radiobuttons into the same 'group'

<HELP>
button widgets are graphical buttons generally used to trigger associated commands. They can be created as ordinary buttons, or as checkbuttons, radiobuttons, or menubuttons

The attributes of button widgets are:

		text					- button caption
		state					- normal or disabled (if disabled, text is greyed out)
		width					- button width, in characters 
		height					- button height, in characters 
		borderwidth				- button border width, in pixels 
		image					- image to display instead of text caption
		font					- text font
		anchor					- caption anchor point: n,ne,e,se,s,sw,w,nw, center
		justify					- caption justif. in its rectangle: left, right, or center
		foreground				- text color
		background				- background color 
		activeforeground		- text color when mouse is pressed over button 
		activebackground		- background color when mouse is pressed over button 
		disabledforeground		- text color when button is disabled
		cursor					- cursor to display when mouse is over button
		default					- if true, button is emphasized
		padx,pady				- size of extra padding space around text
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when widget does not have focus
		highlightcolor			- color of additional border when widget has focus		
		takefocus				- see explanation found under the help keyword 'focus'
		textvariable			- if non-null, names a Tk variable holding the button's string
		underline				- index of text character to underline
		wraplength				- maximum line length before caption text wraps

checkbuttons, radiobuttons, and menubuttons have a few additional attributes: 

		direction				- position of menu relative to button (menubuttons)
		indicatoron				- true if button status indicator is displayed
		menu					- menu to display when button pressed (menubuttons)
		offvalue				- button-associated value when not checked (checkbuttons)
		onvalue					- button-associated value when checked (checkbuttons)
		value					- button-associated value when selected (radiobuttons)
		selectcolor				- caption color when check or radio button selected
		selectimage				- image replacing caption when check or radio button selected
		variable				- variable holding button-associated value

<menu>
	mb := parent("menubutton","Pick Something"); mb("side") := "left";	-- create a menubutton
	descriptor := "b:Item1,b:Item2,s,c:Item3,c:Item4";
	mb(OM) := mb("menu",descriptor);				-- attach a menu
													-- #men gives the number of items in men
<HELP>
SETL menus can contain kinds of three button-like items, and one kind of menu-like item, allowing them to be structured hierarchically. Menus are seen as tuples of menu items, which can be of the types "b" (like a button), "c" (like a checkbutton), "r" (like a radiobutton), and "s" (reference to a cascaded submenu). Two simpler kinds of items, called separators (used to separate menu items into groups so as to ease reading), and tearoffs (used to allow menus to be 'torn off', which makes them self-standing till closed), can also appear. 

Menus are created by operations of the form

		parent("menu",descriptor),
		
where 'descriptor' is a string of comma-separated items of the form  'b:label', 'c:label', 'r:label', 's:label', 's' (a separator), and 't' (a tearoff.) 

Menus have attributes, which in some cases can be over-ridden by separate individual attributes assigned to their menu items.

The attributes of menus are:

		type					- normal, menubar, or tearoff
		foreground				- text color
		background				- background color 
		selectcolor				- color for selector in mcheckbutton and mradiobutton entries
		font					- font for entries
		activeforeground		- text color when mouse is over an entry 
		activebackground		- background color when mouse is over an entry  
		disabledforeground		- text color when entry is disabled
		borderwidth				- menu border width, in pixels 
		activeborderwidth		- menu border width, in pixels 
		cursor					- cursor to display when mouse is over menu
		postcommand				- command to execute just before menu is posted 
		tearoffcommand			- command to when menu is torn off 
		takefocus				- see explanation found under the help keyword 'focus'

<menuitem>
**

<HELP>
SETL menus can contain kinds of three button-like items, and one kind of menu-like item, allowing them to be structured hierarchically. Menus are seen as tuples of menu items, which can be of the types "mbutton" (like a button), "mcheckbutton" (like a checkbutton), "mradiobutton" (like a radiobutton), and "msubmenu" (reference to a cascaded submenu). Two simpler kinds of items, "mseparator" (used to separate menu items into groups so as to ease reading), and "mtearoff" (used to allow menus to be 'torn off', which makes them self-standing till closed), can also appear. Menus have attributes, which in some cases can be over-ridden by separate individual attributes assigned to their menu items.

The attributes of menu items are:

		label					- label of entry
		image					- image to display instead of label
		bitmap					- bitmap to display instead of label
		justify					- label justification: left, right, or center
		foreground				- text color
		background				- background color 
		accelerator				- text for keystroke binding reminder 
		selectcolor				- color for selector in mcheckbutton and mradiobutton entries
		state					- normal, active, or disabled
		font					- font for entries
		underline				- index of text character to underline
		activeforeground		- text color when mouse is over an entry 
		activebackground		- background color when mouse is over an entry  
		disabledforeground		- text color when entry is disabled
		borderwidth				- menu border width, in pixels 
		activeborderwidth		- menu border width, in pixels 
		columnbreak				- start a new menu column with this entry
		command					- command to execute when this entry is selected
		variable				- if non-null, names a Tk variable holding selection state
		value					- value for 'variable' when radiobutton is selected
		onvalue					- value for 'variable' when checkbutton is selected
		offvalue				- value for 'variable' when checkbutton is not selected
		hidemargin				- suppress the margin reserved for button indicators
		cursor					- cursor to display when mouse is over menu
		postcommand				- command to execute just before menu is posted 
		tearoffcommand			- command to when menu is torn off 
		takefocus				- see explanation found under the help keyword 'focus'

<checkbutton>
ckbut1 := parent("checkbutton","Label1"); ckbut1("side") := "left";
ckbut2 := parent("checkbutton","Label2"); ckbut2("side") := "left";
ckbut1("variable,offvalue,onvalue") := "x,r1,r2"; ckbut2("variable,offvalue,onvalue") := "y,r1,r2";

<HELP>
checkbuttons are buttons which have two displayable graphic forms, checked and unchecked. They are normally used to display boolean values. Each such button has a special 'variable' attribute x. The value of this variable, which can be read using the operation Tk.getvar(x) and set using the operation Tk.setvar(x,val), determines whether the button is checked or unchecked. To associate a particular value of the groups 'variable' attribute x with these states, we set the 'onvalue' and offvalue attributes of the button. checkbuttons have the following attributes:

		text				- button caption
		font				- button text font
		width				- button width, in characters
		height				- button height, in lines
		anchor				- position of caption within button: n,s,w,e,ne,se,nw,sw or center
		justify				- justification of button text: left, right, or center
		padx				- extra vertical space around caption
		pady				- extra horizontal space around caption
		wraplength			- width of caption text wrap area, in pixels
		underline			- index of caption character to underline (to indicate accelerator)
		textvariable		- surrogate variable for caption text of button 
		state				- normal, disabled, active (pressed)
		indicatoron			- true if button status indicator is displayed
		activeforeground	- color of button text when active
		disabledforeground	- color of button text when disabled
		background			- background color of button text
		bitmap				- bitmap used as button caption alternative
		image				- image used as button caption alternative
		cursor				- cursor to use when mouse is over button
		activebackground	- background color when mouse is over button
		borderwidth			- width of button border
		variable			- surrogate variable for button checked state
		offvalue			- value of variable when button checked
		onvalue				- value of variable when button not checked
		highlightthickness	- thickness of highlight boundary surrounding button
		highlightbackground	- color of highlight surounding button when does not have focus
		highlightcolor		- color of highlight surounding button when has focus
		relief				- button relief: flat, sunken, raise, ridge, or groove
		selectcolor			- color for radio or check button selector
		selectimage			- alternate image for radio or check button selector
		takefocus			- see explanation found under the help keyword 'focus'

<radiobutton>
radbut1 := parent("radiobutton","Radio1"); radbut1("side") := "left";
radbut2 := parent("radiobutton","Radio2"); radbut2("side") := "left";
radbut1("variable,value") := "x,r1"; radbut2("variable,value") := "x,r2";
-- the common 'variable' and distinct 'values' puts these radiobuttons into the same 'group'

<HELP>
radiobuttons are buttons which have two displayable graphic forms, selected and unselected. Buttons of this kind are ordinarily used in groups, of which only one button at a time is on. They display the value of a set of mutually exclusive selections. Such groups are defined by the fact that all the buttons in the group share a common 'variable' attribute x. The value of this variable, which can be read using the operation Tk.getvar(x) and set using the operation Tk.setvar(x,val), determines which of the members of the button group is on. To associate a particular value of the groups 'variable' attribute x with a particular button, we set the 'value' attribute of the button. Radiobuttons have the following attributes:

		text				- button caption
		font				- button text font
		width				- button width, in characters
		height				- button height, in lines
		anchor				- position of caption within button: n,s,w,e,ne,se,nw,sw or center
		justify				- justification of button text: left, right, or center
		padx				- extra vertical space around caption
		pady				- extra horizontal space around caption
		wraplength			- width of caption text wrap area, in pixels
		textvariable		- surrogate variable for caption text of button 
		state				- normal, disabled, active (pressed)
		indicatoron			- true if button status indicator is displayed
		disabledforeground	- color of button text when disabled
		background			- background color of button text
		bitmap				- bitmap used as button caption alternative
		image				- image used as button caption alternative
		cursor				- cursor to use when mouse is over button
		activebackground	- background color when mouse is over button
		borderwidth			- width of button border
		variable			- surrogate variable for button checked state
		value				- value of surrogate variable when radio button selected
		highlightthickness	- thickness of highlight boundary surrounding button
		highlightbackground	- color of highlight surounding button when does not have focus
		highlightcolor		- color of highlight surounding button when has focus
		relief				- button relief: flat, sunken, raise, ridge, or groove
		selectcolor			- color for radio or check button selector
		selectimage			- alternate image for radio or check button selector
		takefocus			- see explanation found under the help keyword 'focus'

<menubutton>
mb := fr("menubutton","Pick Something");  mb("side") := "left";	-- create a menubutton
descriptor := "b:Item1,b:Item2,s,c:Item3,c:Item4";
mb(OM) := mb("menu",descriptor);							-- attach a menu

<HELP>
menubuttons are buttons which display associated menus when pressed. They have a 'menu' attribute whose value is the menu object to display when the button is pressed; and a 'direction' attribute which determines the position of this menu relative to the button. In more detail, menubuttons have the following attributes:

		text				- button caption
		menu				- menu to display when button pressed
		direction			- direction of menu display relative to button: 
								- above, below, left, right, or flush
		font				- button text font
		width				- button width, in characters
		height				- button height, in lines
		anchor				- position of caption within button: n,s,w,e,ne,se,nw,sw or center
		justify				- justification of button text: left, right, or center
		padx				- extra vertical space around caption
		pady				- extra horizontal space around caption
		wraplength			- width of caption text wrap area, in pixels
		underline			- index of caption character to underline (to indicate accelerator)
		textvariable		- surrogate variable for caption text of button 
		state				- normal, disabled, active (pressed)
		activeforeground	- color of button text when active
		disabledforeground	- color of button text when disabled
		background			- background color of button text
		bitmap				- bitmap used as button caption alternative
		image				- image used as button caption alternative
		cursor				- cursor to use when mouse is over button
		activebackground	- background color when mouse is over button
		borderwidth			- width of button border
		highlightthickness	- thickness of highlight boundary surrounding button
		highlightbackground	- color of highlight surounding button when does not have focus
		highlightcolor		- color of highlight surounding button when has focus
		relief				- button relief: flat, sunken, raise, ridge, or groove
		takefocus			- see explanation found under the help keyword 'focus'

<message>
msg := parent("message","Messages\ncan\noccupy\nmany lines"); msg("side") := "left";

<HELP>
Message widgets are used to display multiple lines of non-editable text. Their height is calulated automatically. Their attributes are:

		text					- text of message
		font					- message text font
		anchor					- message text anchor point: n,ne,e,se,s,sw,w,nw, center
		aspect 					- message width, as percentage of height
		justify					- message justif. in its rectangle: left, right, or center
		textvariable			- if non-null, names a Tk variable holding the message's string
								- Note: this over-rides the 'text' attribute if it has been set 
		foreground				- text color
		background				- background color 
		width					- message width, in characters for text 
		borderwidth				- message border width, in pixels 
		relief					- flat, sunken, raised, groove, or ridge
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when label does not have focus
		highlightcolor			- color of additional border when label has focus		
		cursor					- cursor to display when mouse is over message
		takefocus				- see explanation found under the help keyword 'focus'

<label>
lab := parent("label","Labels\ncan\noccupy\nmany lines"); lab("side") := "left";
lab("height") := 3;		-- their height is specified explicitly

<HELP>
Label widgets are used to display multiple lines of non-editable text, images, or bitmaps. Their height in lines is specified explicitly. Their attributes are:

		text					- text of label
		font					- label text font
		bitmap					- bitmap to display instead of label text 
		image					- image to display instead of label text 
		anchor					- label text anchor point: n,ne,e,se,s,sw,w,nw, center
		justify					- label justif. in its rectangle: left, right, or center
		textvariable			- if non-null, names a Tk variable holding the label's string
								- Note: this over-rides the 'text' attribute if it has been set 
		foreground				- text color
		background				- background color 
		width					- label width, in characters for text, pixels for image 
		height					- label height, in characters for text, pixels for image
		borderwidth				- label border width, in pixels 
		relief					- flat, sunken, raised, groove, or ridge
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when label does not have focus
		highlightcolor			- color of additional border when label has focus		
		cursor					- cursor to display when mouse is over label
		padx,pady				- size of extra padding space around label
		takefocus				- see explanation found under the help keyword 'focus'
		wraplength				- width, in pixels, at which wrap begins

<slider>
slider := parent("scale","0,100");  -- parameters are lower and upper limit of slider range
slider("side") := "top"; 
slider("orient") := "horizontal"; 			-- can be 'vertical'
slider("length,width") := "350,10";			-- physical size of slider

<HELP>
Sliders are used to convert positions along a line into numerical values. They consist of a slider bar ('trough') and a sliding element. One can either drag the sliding element, of hold the mouse down in the trough, which causes the sliding element to move toward the mouse position. 

The attributes of sliders are:

		from,to					- minimum and maximum slider values 
		showvalue				- display value with sliding element
		digits					- number of digits in display value, if any
		resolution				- round value to a multiple of this element 
		orient					- horizontal or vertical
		length,width			- long and short dimensions of the slider trough
		sliderlength			- length of the sliding element
		troughcolor				- color of slider bar
		background				- sliding element and surround color 
		activebackground		- color of sliding element when being dragged 
		foreground				- color of caption text
		state					- normal, active, or disabled
		repeatdelay				- delay till auto-stepping if click in trough
		repeatinterval			- delay between auto-steps if click in trough
		bigincrement			- slider step in response to command-left, command-up, etc.
		variable				- if non-null, names a Tk variable holding the slider value
		cursor					- cursor to display when mouse is over slider
		takefocus				- see explanation found under the help keyword 'focus'
		borderwidth				- slider additional border width, in pixels 
		relief					- flat, sunken, raised, groove, or ridge relief for slider bar
		sliderrelief			- flat, sunken, raised, groove, or ridge relief, sliding element
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when slider does not have focus
		highlightcolor			- color of additional border when slider has focus		
		label					- label to be displayed with slider bar
		font					- label font
		tickinterval			- if nonzero, interval at which to display ticks
		command					- command to invoke when value changes????

<map slider>
	use map_slider;		-- use the map_slider class

	map_slidr := map_slider(Tk,"A@0@255@255;B@0@255@0;C@0@255@0;;X@0@255@255;Y@0@255@0;Z@0@255@0",
			lambda(); end lambda);

<HELP>
A map slider is in effect a slider-controlled, numerically valued map whode domain is the set of labels associated with the slider. They are created by calls of the form 

	ms := map_slider(parent_window_or_frame,"descriptor",response_routine);

The descriptor must be a semicolon-delimited string consisting of @-delimed quadruples of the form 

	Label@lower_limit@upper_limit@default value

each defining one slider label, along with the upper and lower limits for the numerical quantity associated with it, and it inital value. The 'response_routine' which will be called whenver a slider-controlled value changes, should be parameterless. To switch the slider to control the value associated with a particular label, simply click on the  label in the visible form of the map_slider. The value currently associated with any label can be retrieved by writing ms("label"), and set by writing ms("label") := val; this last operation alos adjsuts the visible slider position.

<radio_buttons>
	use radio_buttons;		-- use the radio_buttons class

	j := radio_buttons(fr,"rads1,Opaque*,Darkest     ,Lightest     ",lambda(); end lambda);
	j := radio_buttons(fr,"rads2,Copy     *,Drag     ",lambda(); end lambda);

<HELP>
This class gives an easy way of creating groups of radio buttons. These are created by calls of the form

	junk := radio_buttons(parent,descriptor,response);

 A descriptor for the radio buttons class should have the form v,lab1,lab2,...;v',lab1',lab2',...  where each v names the common variable which ties together a group of radio buttons,  and the following labs are the labels for the buttons. The labs can have preceding and trailing blanks which are just used as spacers but are stripped off in the code. The  very last character of one of the labels can be a '*", n which case the corresponding button will be pre-selected when the buttons first appear. 'response' is the parameterless  response routine to be called when one of the buttons is clicked. The label of the currently  selected button in a group is simply Tk.getvar("v"), where v is the designated   variable for the group.  

<simple_menu>
	use simple_menu_pak;		-- use the simple_menu package

	sm := simple_menu(Tk,"Item1,Item2,,Item3,Item4",lambda(choice); end lambda);

<HELP>
This class gives an easy way of creating simple menu buttons.These are created by calls of the form

	junk := simple_menu(parent,descriptor,response);

A descriptor for a menu of this class should have the form lab1,lab2,..., where the labels should be distinct. The labels can have preceding and trailing blanks which are just used as spacers but are stripped off in the code. Empty labels can be used and will generate separators. 'response' is a 1-parameter response routine to which the selected menu item will be passed when a selection is made.

<listbox>
lb := parent("listbox",3); lb("side") := "left";	-- listbox shows 3 elements
lb(1..0) := "Item1,Item2,Item3,Item4,Item5,Item6,Item7,Item8,Item9,Last Item";
				-- listbox contains 10 elements, so a scrollbar is attached
lb("yscroller") := scroller := parent("scrollbar","v,10"); -- attach a scrollbar
lb("width") := 8;

scroller("side,fill") := "left,y"; -- scrollbar fills available vertical space

<HELP>
Listboxes are used to display lists of items for easy choice. SETL sees them as tuples of strings, nmely the strings which appear in the listbox.

The attributes of listboxes are:
		height					- number of listbox lines visible
		width					- width of listbox, in characters
		font					- item text font
		foreground				- color of item text
		background				- item background color 
		selectforeground		- text color of selected items 
		selectbackground		- background color of selected items  
		borderwidth				- extra border width, in pixels, around the listbox
		selectborderwidth		- extra border width around listbox text items for 3D effect
		selectmode				- single, browse, multiple, or extended. See main documentation 
		setgrid					- if true, restict resizing to whole number of lines and chars
		cursor					- cursor to display when mouse is over listbox
		relief					- relief for entire listbox 
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when listbox does not have focus
		highlightcolor			- color of additional border when listbox has focus		
		takefocus				- see explanation found under the help keyword 'focus'
		yscroller				- vertical scrollbar for the listbox, if any
		exportselection			- if true, exports selected text (XWindows only)

<rastport>
	rast.get_img(gr_img,u,v);	-- move a copy of gr_img to position u, v in rastport, and fill it 
								-- with the bitmap data that it overlays in that position 
	rast.put_img(gr_img,x,y);	-- stuff gr_img into rastport at position x, y
<HELP>
	Rastports are a new form of canvas widget, spcific to SETL's interactive environment, for the efficient display of images of 'grlib' type; see the documentation of 'grlib' in the 'libs' section of this help window and in the main SETL documentation. About 2 dozen rastport operations are provided. The two most charatcteristic rastport operations are

		rast.get_img(gr_img,u,v)
	
which moves a copy of gr_img to position u, v in rastport, and fills it with the bitmap data that it overlays in that position; and  

		rast.put_img(gr_img,u,v);

which moves a copy of gr_img to position u, v in rastport, and stuffs the covered pixels of rastport with the contents of gr_img. This is done in-place, and efficiently. 

Variants of these basic operations which combine gr_img with the contents of rastport are also provided. 

	The operations analogous to rast.put_img are:

rast.put_add(gr_img,x,y);
	(inserts the sum of the rastport data and gr_img into rastport)
rast.put_dif(gr_img,x,y);	
	(inserts difference of the rastport data and gr_img into rastport)
rast.put_mul(gr_img,x,y);	
	(inserts product the rastport data and gr_img into rastport)
rast.put_div(gr_img,x,y);	
	(inserts quotient of the rastport data and gr_img into rastport)
rast.put_min(gr_img,x,y);	
	(inserts the min of the rastport data and gr_img into rastport)
rast.put_max(gr_img,x,y);	
	(inserts the max of the rastport data and gr_img into rastport)
rast.put_blend(gr_img,x,y,c1,c2);
	(blends gr_img with underlying rastport data using coefficients c1 and c2, and stuffs the result into rastport)

	The operations analogous to rast.get_img are:

rast.get_add(gr_img,x,y);
	(returns gr_img copy holding sum of rastport data and gr_img)
rast.get_dif(gr_img,x,y);
	(returns gr_img copy holding difference of rastport data and gr_img)
rast.get_mul(gr_img,x,y);
	(returns gr_img copy holding product of rastport data and gr_img)
rast.get_div(gr_img,x,y);
	(returns gr_img copy holding quotient of rastport data and gr_img)
rast.get_min(gr_img,x,y);
	(returns gr_img copy holding min of rastport data and gr_img)
rast.get_max(gr_img,x,y);
	(returns gr_img copy holding max of rastport data and gr_img)
rast.get_blend(gr_img,x,y,c1,c2);
	(blends gr_img with underlying rastport data using coefficients c1 and c2, and returns the result in a copy of gr_img)

	Finally, a set of rotated cases of the put operations are provided. These act like put_img, put_add, but rotate gr_img by 90 degrees before comining it with the rastport data and stuffin the result into the rastport. These operations have forms like rast.put_imgr(gr_img,u,v), and are named put_imgr, put_addr, put_difr, put_mulr, put_divr, put_minr, put_maxr, and put_blendr. put_blendr, like put_blend, has the form

			rast.put_blendr(gr_img,x,y,c1,c2).
		
<scrollbar>
tex := parent("text","60,4"); tex("side") := "left";    -- create a text area
tex("wrap") := "word";
        
sbv := parent("scrollbar","v,10");          -- create a vertical scrollbar
sbv("side,fill") := "left,y";
tex("yscroller") := sbv;
   
<HELP>
Scrollbars are modified sliders, specially adapted to work with canvases, textlines, and text areas, which are the three kinds of widgets that can scroll. It has a draggable sliding element, clickable arrows, and responds with larger jumps to clicks in the scrollbar (i.e. 'trough'.)

The attributes of scrollbars are:
		orient					- horizontal or vertical
		width,height			- long and short dimensions of the scrollbars
		repeatdelay				- delay till auto-stepping if click in trough or arrows
		repeatinterval			- delay between auto-steps if click in trough or arrows
		jump					- if true, scrolling is not dynamic, but applied when drag ends
		troughcolor				- color of scrollbars
		background				- sliding element and surround color 
		activebackground		- color of sliding element when being dragged 
		activerelief			- relief of sliding element when being dragged 
		borderwidth				- scrollbars additional border width, in pixels 
		elementborderwidth		- additional border width for arrows and slider, in pixels 
		highlightthickness		- thickness of additional border used to indicate focus 
		highlightbackground		- color of additional border when slider does not have focus
		highlightcolor			- color of additional border when slider has focus		
		cursor					- cursor to display when mouse is over scrollbars

<scrollable widgets>

program test;	-- standard template for interactive programs
use tkw,string_utility_pak;		-- use the main widget class

var Tk,global_1,global_2,global_3;

	Tk := tkw(); Tk(OM) := "Caption";						-- create the Tk interpreter
	canv := Tk("canvas","300,300"); canv("row,column") := "1,1"; canv("scrollregion") := "0,0,600,600";
	rect := canv("rectangle","150,150,450,450"); rect("width,foreground,fill") := "1,black,red";
	oval := canv("oval","200,200,500,500"); oval("width,foreground,fill") := "1,black,green";
	rect := canv("rectangle","250,300,475,490"); rect("width,foreground,fill") := "1,black,blue";

	canv("xscroller") := h_scrollbar := Tk("scrollbar","h,16"); h_scrollbar("row,column,sticky") := "2,1,ew"; 
	canv("yscroller") := v_scrollbar := Tk("scrollbar","v,16"); v_scrollbar("row,column,sticky") := "1,2,ns"; 

			-- *** create all the other interface widgets by inserting code here *** 
			
	Tk.mainloop();		-- enter the Tk main loop

	procedure my_procedure();	-- procedures go here
		print("::::");
	end my_procedure;

end test;

<HELP>
Textwidgets and listboxes are inherently 'scrollable', i.e. scrollbars can be attached to them (see the 'scrollbar' help entry. Frames are not scrollable. Canvases can be made scrollable by setting their 'scrollregion' attribute, as in 

		canv("scrollregion") := "0,0,600,600";

Note that scrollbars are best positioend  near the widget they control by gridding, e.g.

		h_scrollbar("row,column,sticky") := "2,1,nesw";

The 'sticky' setting causes the scrollbar to expand to  the full horizontal and vertical extent of the area avaialble to it.

<dialog>
Tk("ask_ok","type,default,message") := "ok,ok,Proceed"; 
Tk("ask_ok","type,default,message") := "yesnocancel,no,Do you want to see the rest of these dialogs?";
if dialog_response = "yes" then 
	Tk("ask_file","") := "";  
	Tk("ask_save_file","") := "";  
	Tk("ask_color","initialcolor,title") := "red,Pick a Color";
end if;

<HELP>
The SETL graphical interface provides several types of utility dialogs: "ask", "ask_ok", "ask_file", "ask_save_file", and "ask_color".

The "ask" dialog presents a set of captioned buttons, of which one can be designated as the default, and can include a bitmapped icon.  Its attributes are:
		labels					- list of labels to appear
		default					- number of default label			
		message					- message to appear
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog is to appear
		icon					- bitmap to appear, if any

The "ask_ok" dialog is a specialized variant of the "ask" dialogs, which presents one, two, or three buttons, depending on its type, which can be yesno, ok, okcancel, retrycancel, yesnocancel, or abortretrycancel.  Its attributes are:
		type					- dialog type, as just listed
		default					- number of default label			
		message					- message to appear
		icon					- bitmap to appear, if any
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog is to appear
		
The "ask_file" dialog opens the standard system 'select/open file' utility. Its attributes are:
		filetypes				- list of file types to be shown. If empty, all are shown
								- see the main documentation for the format of this list
		initialdir				- initial directory whose contents shown; current dir if empty
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog appears (Unix and Windows)

The "ask_save_file" dialog opens the standard system 'save file' utility. Its attributes are:
		filetypes				- list of file types to be shown. If empty, all are shown
								- see the main documentation for the format of this list
		initialdir				- initial directory whose contents shown; durrent dir if empty
		initialfile				- default file name
		defaultextension		- default file extension, if none given
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog appears (Unix and Windows)

The "ask_color" dialog opens a color picker. Its attributes are:
		initialcolor			- inital color, when picker dialog opened
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog appears (Unix and Windows)

<filedialog>
	Tk("ask_file","") := "";  		-- dialog for reading a file
	if dialog_response /= "" then the_file := dialog_response; end if;

	Tk("ask_save_file","initialfile") := "useless_junk.jnk";  		-- for saving a file
	if dialog_response /= "" then the_file := dialog_response; end if;

<HELP>
********helptext********
<colorpicker>
Tk("ask_color","initialcolor,title") := "red,Pick a Color";
if dialog_response /= "" then the_color := dialog_response; end if;
<HELP>
The SETL graphical interface provide several types of utility dialogs, including "ask_color", which opens a color picker whose attributes are:
		initialcolor			- inital color, when picker dialog opened
		parent					- toplevel in which dialog is to appear
		title					- title of toplevel in which dialog appears (Unix and Windows)

<clipboard>
Tk("clipboard") := 3 * Tk("clipboard");		-- copy something, run this program, and then paste it

<HELP>
The 'clipboard' is an in-RAM file of string data used to communicate between separate applications. When a selection is 'copied'  (or 'cut') is most text-oriented applications, a copy of it is put into the keyboard. When the 'paste' operation available in most such applications is used, the text which appears is that contained in the clipboard. The SETL interface provides operations which allow the clipboard contents to be manipulated directly.
These are

	Tk("clipboard")				-- returns the current string value in the clipboard
	Tk("clipboard") := stg;		-- sets the current string value in the clipboard

When communicating via clipboard with another SETL application, it may be convenient to pass a binary string encoding a SETL value (e.g. a map), and to decode it on receipt; although the code for this is simply 
	
	Tk("clipboard") := binstr(x);	and	y := unbinstr(Tk("clipboard"));
	
it allows arbitary SETL values to be passed via the clipboard.

<pack>
msg := parent("message","Long message");  msg("side") := "top";
but := parent("button","Label"); but("side,fill") := "top,y";

msg2 := parent2("message","Long message");  msg2("side") := "top";
but2 := parent2("button","Label"); but2("side,fill") := "top,both";

<HELP>
The items 'packed' into a frame appear in the frame's ordered 'packing list', and their positions and sizes are then calculated using their side, padx, pady, ipadx,ipady, expand, fill, and anchor settings. The packing list is manipulated by setting the 'in' attribute, making assignments to the 'after', 'before', or 'children' attributes, or setting obj("side") := OM to remove it from the packing list to which it belongs. To get or set one of a widget's packing-related attributes (see the list below) an attribute list starting with one of the keywords 'pack or 'side' must be used. Wnen 'pack' is used it plays only a syntactic role, and no attribute value should be assigned to it.    

The attributes involved in widget packing are:
		side				- edge (top, bottom, left, right) toward which widget is packed
		in					- widget, other than parent, in which this widget should be packed
							- Note: can only pack into frame belonging to same toplevel
		after				- widget that this should follow in packing order
		before				- widget that this should precede in packing order
		anchor				- position in available space that item should occupy:
							- (n, s, e, w, ne, se, nw, sw, or center) 
		expand				- if true, widget will claim available space in all directions
		fill				- none, x, y, or both: widget fills empty space in that direction
		padx,pady			- size of extra padding space around item packed
		ipadx,ipady			- size of extra internal padding space around item packed
		children			- ordered list of items packed within a frame
		adjust				- if true, frame will adjust to minimum size required for children

<grid>
msg := parent("message","Long message");  msg("row,column") := "1,1";
but := parent("button","Label"); but("row,column") := "1,2";

msg2 := parent2("message","Long message");  msg2("row,column") := "2,2";
but2 := parent2("button","Label"); but2("row,column,sticky") := "2,1,news";

<HELP>
All the items 'grid-placed' into a frame are assigned roa and column positions within a rectangular arangement of implicit 'boxes', which are given box-sizes just large enough to hole their assigned contents. To get or set one of a widget's grid-placement related attributes (see the list below) an attribute list starting with one of the keywords 'grid', 'row', or 'column' must be used. When 'grid' is used it plays only a syntactic role, and no attribute value should be assigned to it.

The attributes involved in grid placement of widgets are:
		row, column			- row and column in which widget is placed
		rowspan				- number of rows occupied by widget
		columnspan			- number of columns occupied by widget
		in					- widget, other than parent, in which this widget should be placed
							- Note: can only placed in frame belonging to same toplevel
		sticky				- edges in available space to which item should adhere,
							- by enlarging if necessary (n, e, s, and w, e.g 'news') 
		padx,pady			- size of extra padding space around item packed
		ipadx,ipady			- size of extra internal padding space around item packed
		children			- ordered list of items grid-placed within a frame
		adjust				- if true, frame will adjust to minimum size required for children

<place>
but := parent("button","Label"); but("place,x,y") := "5,5";
but2 := parent("button","Label"); but2("place,x,y") := "15,15";

<HELP>
Items are 'manually placed' into a given frame by being assigned a position, height, and width. To get or set one of a widget's manual-placement related attributes (see the list below) an attribute list starting with the keywords 'place'must be used. This plays only a syntactic role, and no attribute value should be assigned to it.

The attributes involved in manual placement of widgets are:
		x,y					- x and y pixel positions of anchor point
		relx,rely			- x and y positions of anchor point, as fraction of frame
		width,height		- pixel width and height of widget
		relwidth,relheight	- width and height of widget, as fraction of frame
		anchor				- point in widget occupying stated position:
							- (n, s, e, w, ne, se, nw, sw, or center) 
		in					- widget, other than parent, in which this widget should be placed
							- Note: can only placed in frame belonging to same toplevel
		children			- ordered list of items manually placed within a frame

<event>
**

<HELP>
For more explanation of the way in which widgets and canvas or text items are made sensitive to events, see the main documentation, or the on-line help item 'binding events'. This section expains the kinds of events available, and the way in which they can be created and transmitted under program control.

Widgets and tags can be sensitive to the variety of events seen in the following list: 

	 buttonpress          - mouse button pressed
	 buttonrelease        - mouse button released
	 keypress             - keyboard key pressed
	 keyrelease           - keyboard key released
	 motion               - mouse moved
	 enter                - mouse enters widget
	 leave                - mouse leaves widget
	 double               - mouse doubleclick
	 triple               - mouse triple
	 focusin              - widget gains keyboard focus
	 focusout             - widget loses keyboard focus
	 map                  - window is opened
	 unmap                - window is iconified
	 circulate            - window stacking order changes
	 visibility           - window visibility has changed
	 destroy              - window was destroyed
	 expose               - window has been exposed
	 configure            - size, position, border, or stacking order has changed
	 gravity              - widget has moved because of change in size of its parent window
	 colormap             - color map has changed
	 activate             - the SETL application has been activated
	 deactivate           - the SETL application has been deactivated
	 reparent             - window has been reparented???
	 property             - a window property has been changed or removed???
	 cut                  - system dependent keypress event designating 'Cut'
	 copy                 - system dependent keypress event designating 'Copy'
	 paste                - system dependent keypress event designating 'Paste'
	 
Each of these events can generates a callback to SETL when it occurs.

One particular type of event is designated as each type of widget's 'principal' event. The following table shows these principal events:

	button		- (first) button down
	menu		- (first) button up
	frame		- mouse motion with (first) button down
	toplevel	- mouse motion with (first) button down
	textline	- loss of focus
	listbox		- (first) button up
	text		- loss of focus
	canvas		- mouse motion with (first) button down
	arc			- (first) button down
	bitmap		- (first) button down
	image		- (first) button down
	line		- (first) button down
	oval		- (first) button down
	polygon		- (first) button down
	rectangle	- (first) button down

Tags in canvases or text (see below) can also be event sensitive; their 'principal' event is (first) button down.

Events normally occur as a result of user mouse or keyboard actions. However, events can be created and transmitted to designated widgets and canvas  under program control. To create and  transmit an event, to a widget W, we write 
	
		W{"event_descriptor:event_fields_signature"} := event_parameter_vals;

where 'event_descriptor' and 'event_fields_signature' have the form detailed in the on-line help item 'binding events' and where 'event_parameter_vals' is either a comma-separated sting or a tuple of corresponding event parameter values. An example is 

	top_frame{"B1-Move:xy"} := "25,25";
	top_frame{"B1-Move"} := "";

As seen, the colon used in this event-binding syntax is only required if a non-empty event_fields_signature follows it.

<timed events>
but := parent("button","Click me"); but("side") := "top";
but("font") := "{Times 12}"; global_1 := but; global_2 := true;
but{OM} := start_it;

procedure start_it(); 		-- start the wild action
	global_1("text") := "Click me again before I go crazy"; 
	global_1{OM} := lambda(); global_2 := global_1; global_1 := OM; end lambda; 
	flicker();		-- start the wild action
end start_it;

procedure flicker();  		-- take the wild action
	if global_1 = OM then 		-- stop when global_1 is dropped
		global_2("text") := "What a relief!"; return; 
	end if;
	global_2 := not global_2; 
	global_1("font") := if not global_2 then "{Times 12}" else "{Times 24}" end if;
	Tk.createtimer(500,flicker);	-- repaet twice each second
end flicker;

<HELP>
SETL callback procedures can be invoked after a specified delay, or whenever the interface quiesces and becomes idle. To set up a timed call, one writes 

			id := Tk.createtimer(interval,SETL_fun);

Here 'interval' is the time, in milliseconds, before the parameterless SETL function 'SETL_fun' is to be invoked. This call returns an identifier for the pending timer event, which can be cancelled any time before it has taken place by writing  

			Tk.cancel(id);

To set up a 'when-idle' call that will be triggered when the interface quiesces, write 

			id := Tk.createtimer(OM,SETL_fun);

<binding events>
but := parent("button","Press and hold me; then release the button");
but("side") := "top";
but{OM} := Tk.beeper;		-- set up button to beep once when released
							-- and 3 times when first pressed
but{"ButtonPress-1"} := lambda(); for j in [1..3] loop Tk.beeper(); end loop; end lambda;
print(but{OM}, " ",but{"ButtonPress-1"});		-- print the assigned procedure names

<HELP>
Event handlers for the various kinds of mouse, keyboard, and other events to which Tk widgets and canvas
items are sensitive are set up by writing nominal assignments having one of the two the syntactic forms 

   widget{"event_descriptor:event_fields_signature"} := SETL_procedure;

  text_widget{"tag_name","event_descriptor:event_fields_signature"} := SETL_procedure;

  canvas{"tag_name","event_descriptor:event_fields_signature"} := SETL_procedure;

The first form is used to assign callback procedures to widget-related events; the second and third to
assign callback procedures to tags in text fields and canvases.

The event_fields_signature should be a string consiting of the  single-character codes for the event parameters to be transmitted to an event's handler (see the on-line help sction 'event parameters'.) When an event of the designated type subsequently occurs, the corresponding parameter values will be read from the 'event record' always associated with the event, and collected into a parameter list. This will be transmitted to the callback procedure, which must have exactly one parameter. 

Examples are 

   top_frame{"B1-Move:xy"} := my_drag_procedure1;
   my_button{"ButtonPress-1"} := my_clickstart_procedure1;
   my_canvas{"all_ovals","ButtonRelease-1:t"} := print_click_time;

As seen, the colon used in this event-binding syntax is only required if a non-empty event_fields_signature follows it.

<event parameters>
but := parent("button","Click me to get the time in milliseconds and the click location"); 
but("side") := "top";
but{"ButtonRelease-1:txy"} := lambda(params); 
									[the_time,x,y] := params; 
									print("time: ",the_time," x: ",x," y: ",y); 
							 end lambda;
		
<HELP>
Events have various possible attributes, which can be transmitted as parameters to their associated callback procedures. As seen in the following table, every possible event attribute has an associated single-character code. 

    CODE    DESCRIPTION OF PARAMETER      EVENTS USED FOR; VALUES

     #    -  event serial number             all events
     a    -  'above' field for event         configure event
     b    -  button number            buttonpress, buttonrelease
     c    -  event count field               expose, map
     d    -  event detail field       enter, leave, focusin, focusout
     f    -  focus value established by event      enter, leave
     h    -  height field                    configure, expose
     k    -  keycode                         keypress, keyrelease
     m    -  mode                     enter, leave, focusin, focusout
     o    -  override redirect               map, reparent, configure
     p    -  place                placeontop, placeonbottom, circulate
     s    -  state                buttonpress, buttonrelease, enter, 
                                  leave, keypress, keyrelease, motion
     t    -  time                            all events
     v    -  value mask                      configure event
     w    -  width                           configure, expose
     x    -  horizontal position, widget relative  all mouse events
     y    -  vertical position, widget relative    all mouse events
     A    -  printing character              keypress, keyrelease
     B    -  border width                    configure event
     E    -  sendevent field                 all events
     K    -  key symbol                      keypress, keyrelease
     N    -  key symbol in decimal           keypress, keyrelease
     R    -  root window id                  all events
     S    -  subwindow id                    all events
     T    -  type field                      all events
     W    -  pathname of widget receiving the event        all events
     X    -  horizontal position   absolute buttonpress, buttonrelease, 
                                             keypress, keyrelease, motion
     Y    -  vertical position     absolute buttonpress, buttonrelease, 
                                             keypress, keyrelease, motion

<event qualifiers>
but := parent("button","Click me to beep; Option-click to beep twice; try Command-Option-click."); 
but("side") := "top";
but{"ButtonRelease-1"} := Tk.beeper;
but{"Option-ButtonRelease-1"} := lambda(); Tk.beeper(); Tk.beeper(); end lambda;
but{"Command-Option-ButtonRelease-1"} := 
		lambda(); for j in [1..4] loop Tk.beeper(); end loop; end lambda;

<HELP>
Button- and keypress-related descriptors can further be qualified by attaching 'modifier' prefixes and 'detail' suffixes, separated from the main descriptor keyword by dashes. 'Detail' suffixes specify a keysymbol for keypress events and button numbers for button events. Thus we can have Keypress-a, Keyrelease-Z, Buttonpress-1 (mousedown with first button), etc. The system allows for up to 5 mouse buttons. 'Modifier' prefixes define keys or buttons that must have been pressed for a modified event to occur, and are also used in a few other special situations. The available modifier prefixes are

    Control             - control key must be down
    Shift               - shift key must be down
    Lock                - shift lock must be down
    Command             - command (Apple) key must be down (Macintosh only)
    Mod1 thru Meta 5    - specified one of 5 special keys must be down 
                            (mapped in system-dependent fashion)
    B1 thru B5          - designated button must be down
    Double              - event must occur twice rapidly, (e.g 'doubleclick')
    Triple              - event must occur three times rapidly, (e.g 'tripleclick')
    Meta                - Key Modj regarded as 'system meta-key' must be down
    Alt                 - Key Modj regarded as 'system alt-key' must be down

Use of such prefixes (and of 'detail' suffixes if desired)  gives us modified event descriptors like B1-motion (drag with first mouse button down), Command-a, Double-Buttonrelease-1 (doubleclick with button 1), etc.  

Modifier prefixes, but not detail suffixes, can be repeated, in lists separated by the '-' character. This gives us such still more closely specified events as Command-Shift-B1-motion (drag with first mouse button and two additonal keys down), Double-B1-Buttonrelease-1 (doubleclick with button 1 while holding first mouse button down), etc.

<arc>
ca := parent("canvas","200,200"); ca("side") := "top";		-- the arc needs a canvas
ark := ca("arc","10,10,50,50"); ark("start,extent,fill") := "0,90,red";
ark2 := ca("arc","110,10,150,50"); ark2("start,extent,style") := "0,150,chord";
ark3 := ca("arc","10,110,50,150"); ark3("start,extent,style") := "0,190,arc";

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For arcs, these are the left, top, right, bottom of the enclosing rectangle of the oval on which the arc lies.

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of an arc are:
		style				- pieslice, chord, or arc (circular boundary only)
		start				- starting angle of circular arc, in degrees
		extent				- extent of circular arc, in degrees
		width				- width of outline
		fill				- color for interior
		outline				- color for outline
		stipple				- pattern for interior
		outlinestipple		- pattern for outline

<bitmap>
bitmaps := [["error", "hourglass", "info", "questhead"], ["question", "warning", "gray50", "gray12"]];

for j in [1..2], k in [1..4] loop
	canv_jk := parent("canvas","30,30"); canv_jk("row,column") := [j,k];
	bm_jk := canv_jk("bitmap","15,15");		-- the second parameter is the bitmap anchor point
	bm_jk("bitmap,anchor,foreground,background") := bitmaps(j)(k) + ",center,blue,yellow";
end loop;

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For bitmaps these are the x and y coordinates of the bitmap's anchor point (e.g. center.)

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a bitmap are:
		bitmap				- file name or built-in bitmap name defining picture geometry
		anchor				- point from which position is reckoned: center,n,s,e,w,nw,sw,ne, or se
		background			- display color for bitmap background
		foreground			- display color for bitmap foreground

Built-in bitmaps with the following names are provided by the SETL interface:

	error, hourglass, info, questhead, question, warning, gray50, gray12 

<line>
ca := parent("canvas","200,100"); ca("side") := "top";
line := ca("line","140,20,180,20,180,40,20,40"); line("arrow,fill,smooth") := "both,blue,true";

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For lines (open curves) these are the x and y coordinates of the controlling vertices (note that 'lines' can be splines.)

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a line (open curve) are:
		width				- line width
		smooth				- if true, line is a spline curve 
		splinesteps			- number of intermediate smoothing points to use, if spline
		fill				- line color
		stipple				- line pattern
		joinstyle			- line corner join style: bevel, miter, or round
		capstyle			- line end style: butt, projecting, or round		
		arrow				- should arrowheads be drawn: none, first, last, or both
		arrowshape			- tuple [overall length, length from point to line end, width]	
<oval>
ca := parent("canvas","200,100"); ca("side") := "top";
oval := ca("oval","80,20,120,40"); oval("width,stipple") := "5,gray12";

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For ovals these are the left, top, right, bottom of the enclosing rectangle.

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of an oval are:
		width				- width of outline
		fill				- color for interior
		outline				- color for outline
		stipple				- pattern for interior

<rectangle>
ca := parent("canvas","200,100"); ca("side") := "top";
rect := ca("rectangle","20,20,200,200"); rect("width,fill,outline") := "10,red,blue";

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For rectangles these are its left, top, right, and bottom.

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a rectangle are:
		width				- width of outline
		fill				- color for interior
		outline				- color for outline
		stipple				- pattern for interior

<polygon>
ca := parent("canvas","200,200"); ca("side") := "top";
poly := ca("polygon","40,60,180,60,180,100,30,30,20,150"); 
poly("fill,smooth,width,outline") := "yellow,true,3,red";

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For polygons (closed curves) these are the x and y coordinates of the controlling vertices (note that 'polygons' can be splines.)

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a polygon (closed curve) are:
		width				- polygon outline width
		smooth				- if true, polygon is a spline curve 
		splinesteps			- number of intermediate smoothing points to use, if spline
		fill				- color for polygon interior
		outline				- color for polygon outline
		stipple				- pattern for arc interior

<canvastext>
ca := parent("canvas","400,200"); ca("side") := "top";
ct := ca("text","Red text in the canvas"); 
ct("coords") := "30,30"; ct("anchor,font,fill") := "nw,{Times 36},red";	
ct2 := ca("text","Blue text in the canvas"); 
ct2("coords") := "130,40"; ct2("anchor,font,fill") := "center,{Times 36},blue";	

<HELP>
Canvas items are entities, typically geometric, that can be drawn in the rectangle occupied by a canvas. The geometric objects allowed are rectangle, arc, bitmap, image, line, oval, polygon, text, and image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For canvas text items these are the x and y coordinates of the text rectangle's anchor point (e.g. center.)

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a canvas text item are:
		text				- actual text string
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se
		font				- text font, e.g. "Times,20,bold"
		justify				- left, right, or center
		fill				- text color
		stipple				- text pattern
		width				- text area width 

<image>
ca := parent("canvas","400,200"); ca("side") := "top";
abs_img := Tk("image","orchidbig.GIF");			-- read an absolute image
img := ca("image",abs_img); 			-- use the absolute image in a first canvas image
img("coords") := "30,30"; img("anchor") := "nw";	

<HELP>
'Image' objects of two kinds are used in the SETL widget system. 'Absolute' images are data files of images that can be drawn, but may not yet have been drawn. 'Canvas' images are absolute images that have been placed in a canvas, and therefore drawn.

Absolute image objects can be read from files using commands of the form

	img := tkw_name("image",file_name);

where 'tkw_name' is the name of the master widget object. They can also be created by 'photographing' part of a canvas using  commands of the form

	img := canvas_name.image_of([l,t,r,b]).
		
Finally, they can be created from 'image library' images using commands of the form 

	img := tkw_name("image",img_library_object);

The attributes of an absolute image item are:
		file				- source file containing image data
		data				- alternative to 'file': image data as base64 string
		height, width		- height and width of image
		format				- data format for file or data string, e.g. GIF, PPM, PGM
		palette				- image color palette
		channel				- open channel or socket from which to get image data
		
<canvasimage>
ca := parent("canvas","400,200"); ca("side") := "top";
abs_img := Tk("image","orchidbig.GIF");			-- read an absolute image
img := ca("image",abs_img); 			-- use the absolute image in a first canvas image
img("coords") := "30,30"; img("anchor") := "nw";	

<HELP>
'Image' objects of two kinds are used in the SETL widget system. 'Absolute' images are in effect data files of images that can be drawn, but may not yet have been drawn. 'Canvas' images are absolute images that have been placed in a canvas, and therefore drawn. So canvas images (but not absolute images), are like the other canvas items that can be drawn in the rectangle occupied by a canvas, i.e. rectangle, arc, bitmap, image, line, oval, polygon, text, and canvas image.

The size, shape, and position of a canvas item is defined by its associated set of coordinates, given by its "coords" attribute. For canvas images these are the x and y coordinates of the images's anchor point (e.g. center.)

Each item can also have an associated list of tags, given by its "tags" attribute.

The attributes of a canvas image item are:
		image				- image object to appear in canvas item
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se

<canvaswidget>
ca := parent("canvas","400,200"); ca("side") := "top";
ovall := ca("oval","10,10,100,150"); ovall("fill") := "red";

but := parent("button","This button will be put directly into the Canvas"); 
but_incanv := ca("widget",but); but_incanv("coords,anchor") := "30,30;nw";

parent2 := Tk("frame","100,50");		-- this frame will be put directly into the Canvas
parent2_incanv := ca("widget",parent2); parent2_incanv("coords,anchor") := "50,40;nw";

lb := parent2("listbox",3); lb("side") := "left";	-- listbox shows 3 elements
lb(1..0) := "Item1 Item2 Item3 Item4 Item5 Item6 Item7 Item8 Item9 Item10";
				-- listbox contains 10 elements, so a scrollbar is attached
lb("yscroller") := scroller := parent2("scrollbar","v,10"); -- attach a scrollbar
lb("width") := 8; 

scroller("side,fill") := "left,y";		-- make the scrollbar visible

ovall2 := ca("oval","40,10,130,150"); ovall2("fill") := "blue";

<HELP>
Widgets of any other kind can be drawn to canvases, so that canvases can be structured as collages of basic geometric abjects and subcanvases. The position of such a 'canvas widget' is defined by its "coords" attribute, which are the x and y coordinates of the images's anchor point (e.g. center.)

The two attributes of a canvas widget are:
		widget				- widget object to appear in canvas item
		anchor				- point from which position is reckoned: n,s,e,w,nw,sw,ne, or se
		
Note that canvas widgets are drawn above othe kinds of canvas items.
<tag>
**

<HELP>
********* help text*********

<visual>
**

<HELP>
********* help text*********

<title>
toplevel(OM) := "title_for_my_window";

<HELP>
The title of a toplevel widow is set simply by assigning to its 'OM' attribute, e.g.

		toplevel(OM) := "title_for_my_window";


<cursor>
parent("cursor") := "bogosity"; parent2("cursor") := "iron_cross";

<HELP>
Built-in cursors with the following names are provided:

Arrow cursors:
	arrow, double_arrow, based_arrow_down, based_arrow_up, 
	draft_large, draft_small, top_left_arrow, right_ptr, 
	center_ptr, right_side, left_side, bottom_side, top_side,
	center_ptr, sh_h_double_arrow, sh_v_double_arrow, 
	sh_left_arrow, sh_right_arrow, sh_up_arrow, sh_down_arrow

Cross cursors:
	xterm, x_cursor, plus, tcross, crosshair, spider, fleur, 
	iron_cross, diamond_cross, cross_reverse, cross

T and angle cursors:
	right_tee, left_tee, bottom_tee, top_tee, ll_angle, 
	lr_angle, ul_angle, ur_angle,

Corner cursors:
	bottom_left_corner, bottom_right_corner, top_left_corner, 
	top_right_corner, 

Box cursors:
	dotbox, draped_box, sizing, middlebutton, rightbutton, 
	leftbutton, target, box_spiral,

Miscellaneous cursors:
	 dot, icon, rtl_logo, exchange, mouse, spraycan, pencil, 
	 star, boat, bogosity, pirate, man, question_arrow, 
	 gobbler, gumby, hand1, hand2, heart, trek, clock, circle, 
	 coffee_mug, sailboat, umbrella, watch, shuttle

<fonts>
Tk("font","my_favorite_font,family,size,slant") := "Sabon,18,roman";
Tk("font","a_hateful_font,family,size,slant") := "{Arial Black},36,italic";
mes := parent("message","Hello World"); mes("side") := "top";
mes("font") := "{my_favorite_font}";
mes2 := parent("message","Hello World"); mes2("side") := "top";
mes2("font") := "{a_hateful_font}";
print(Tk("definedFonts"));
print(Tk.font_metrics("{Times}"));
print(Tk.measure_fonted("Now is the time","{Times 24}"));

<HELP>
Fonts are ordinarily indicated in the style illustrated by {Sabon 24 {bold italic}} or 
{{Zapf Dingbats} 24 {bold underline}}. The available font attributes, set by these designators, are 
family (e.g. Sabon or {Zapf Dingbats}), size, weight ('bold' or 'normal'), slant ('roman' or 'italic'), underline ('true' or 'false'), overstrike ('true' or 'false').

A level of indirection, facilitating font substitution where desired, is available through the use of defined fonts. To define a font and set its attributes, we write 

		Tk("font","new_name,attributes") := attribute_vals;

where 'attributes' is a comma-separated list of attribute names, and 'attribute_vals' is a list of corresponding values. An example is

		Tk("font","my_favorite_font,family,size,weight") := "Sabon,18,roman"

Font names introduced in this way can be used in the place of ordinary fonts, e.g. given a message object 'mes' we can write 

		mes("font") := my_favorite_font;

The expression Tk("fonts") returns a list of all the currently available fonts (not including the defined fonts.) The expression Tk("definedFonts") returns a list of all the currently defined fonts.
Tk.font_metrics(font) returns basic metric information about a font, as a map from the attribute names "fixed", "linespace", "ascent", "descent" to their integer values. The 'font' parameter should be supplied in the form illustrated by "{Zapf Dingbats}". Tk.measure_fonted(stg,font) returns the pixel width of the string 'stg' when set in the font 'font' (ignoring the special effects of tabs and linebreaks.)
<grab>
win := TK("toplevel","10,10"); win(OM) := "You must click this button";
but := win("button","Click Here or Die!"); but("side") := "top";
but{OM} := cleargrab(win);
win("grab") := "global";

procedure cleargrab(win); 
	return lambda(); win("grab") := OM; end lambda; 
end cleargrab;

<HELP>
The operation window("grab") := "global" (or OM, or anything else) can be used to set a toplevel window of the SETL interface into a 'modal' stte in which user interaction with other windows is restricted or suppressed. Setting window("grab") := "global" suppresses all interactions with other windows. window("grab") := OM clears the grab. Any other grab value suppresses interactions with other interface windows, but not with other applications.
<update>
Tk.update();
<HELP>
A SETL routine R running after being called in consequence of an initial interface-related event (even an interface timer event) can call the routines of the tkw package to request display and other graphic services, but ordinarily these will not be posted (become visible) in the interface until R completes. To ensure that such graphic changes become visible immediately, the procedure 'Tk.update()' should be called immediately after the calls defining the desired graphic changes. 

<sockets>
program test;				-- test the socket function
	use socket; 			-- i.e. use the client and server socket class
	var sock; 				-- socket object used globlly
	
	sock := socket("www.att.com:80","text");	-- create a client of known port 80
	sock{">"} := readsock(sock);			-- socket contents reader for client
	sock(OM) := "GET /\r\n\r\n";
	
	sock.mainloop();		-- enter the socket main loop
	sock.close();			-- close socket for courtesy at program end
	
	procedure readsock(sock);					-- socket contents reader for client 
		return lambda(x);		-- bind the socket  into the reader
			cameback := sock(OM); print("Received: ",if sock.error = "" then "Final, possibly blank line: " else "" end if,cameback); 
			if sock.error = "" then print("Client socket closed - EOF:",sock); sock.close(); end if; 
		end lambda;
	end readsock;

end test;
<HELP>
SETL socket objects  provide an interface to Berkely TCP/IP sockets via the TCL socket facility. They come in two basic kinds, 'client sockets' that are pipe-like objects either of whose two ends can be read or written, and 'server sockets' that attach associated 'server handler' procedures to a specified, numbered TCP/IP port. Once this is done client-socket requests-for-connection arriving via Internet automatically spin off new client sockets and pass them via event-like calls to their associated 'server handlers'. To create a socket, calls of one of the three forms

	socket("host:port","TEXT");		-- line-buffered client socket
		-- request 'client' connection to specified host and port

	socket("host:port",buf_size);	-- block-buffered client socket
		-- request 'client' connection to specified host and port

	socket(portno,request_handler);	-- server socket
		-- attach server to specified port on this host

Details concerning these various options are found in the help items following this one. 

Every socket exposes a 'main loop' method [sock.mainloop()], precisely identical to the Tk-widget 'main loop' method; any one (but just one) of these calls  should be made to hold SETL in a potentially interactive, non-blocking event loop  for  as long as a set of sockets (or other asychronously acting objects) are to be used.

Client sockets provide the two i/o methods 

	self(x);		-- reads the socket; 

and 
	
	self(x) := y;	-- writes string y to the socket
	
In both these calls the parameter x, present only for syntactic reasons, is ignored. Read calls return OM in case of error, otherwise the string read. The socket's error attribute sock.error is set to the null string if an endfile is encountered, otherwise to 0 for sucessful reads and an error message in case of errors. Client sockets will block if they are read when they are not 'read-ready' (or written when they are not 'write-ready'.) To receive a signal when client sockets pass into these states, one attaches i/o handlers to them, usng a call of the form

	self{x} := handler_proc;		-- set up socket event handlers

The parameter x should either be ">" (if the socket 'read-ready' handler is being defined) or the 'greater-than' sign (if the socket 'write-ready' handler  is being defined). These handlers are good places to perform the socket read and write operations in asynchronous fashion.

Once created, sockets can be closed using the parameterless operation

	sock.close().

<client io handler>
procedure readsock(sock);			-- socket contents reader for client 
	return lambda(x);		-- bind the socket  into the reader
		cameback := sock(OM); print("Received: ",if sock.error = "" then "Final, possibly blank line: " else "" end if,cameback); 
		if sock.error = "" then print("Client socket closed - EOF:",sock); sock.close(); end if; 
	end lambda;
end readsock;
<HELP>
These (necessarily parameterless) routines, attached to client sockets  by calls of the form

	self{x} := handler_proc;		-- set up socket event handlers

are called when their associated sockets pass into read-ready' (or 'write-ready') state. They are good places to perform the socket read and write operations in asynchronous fashion, as shown in the example above. The parameter x should either be ">" (if the socket 'read-ready' handler is being defined) or or the 'greater-than' sign (if the socket 'write-ready' handler  is being defined).

<server handler>

procedure request_acceptor(x);				-- request acceptor for server socket
	print("Accepted: ",x); [newsock_name,calling_host,calling_port] := x; 
	print("newsock: ",newsock := socket(newsock_name + ":","TEXT"));
					-- turn socket name into socket object, appropriately configured
	newsock(OM) := "Hello there. You are client number " +  str(clno +:= 1);
					-- write a line back
	newsock{">"} := readnewsock;
end request_acceptor;

procedure readnewsock(x); print("Received new: ",newsock(OM)); newsock.close(); end readnewsock; 	-- socket contents reader for generated client sockets on server end

<HELP>

<reading socket>
cameback := sock(OM);
<HELP>
The i/o method 

	self(x);
	
is used to read a (necessarily clinet-type) socket. The parameter x is ignored. Read calls return OM in case of error, otherwise the string read. The socket's error attribute sock.error is set to the null string if an endfile is encountered, otherwise to 0 for sucessful reads and an error message in case of errors. Client sockets will block if they are read when they are not 'read-ready' (or written when they are not 'write-ready'.)

<writing socket>

<HELP>
The i/o method 

	self(x) := y;
	
is used to write a (necessarily client-type) socket. The parameter y must be a string; the parameter x is ignored. Client sockets will block if they are  written when they are not 'write-ready'.

<socket.close>
	sock.close();			-- close socket for courtesy at program end

<HELP>
Sockets are closed using the parameterless operation

	sock.close().
<SECTION=Libs>
<Library List>
set_library_list(lib_name1,lib_name2,...);
<HELP>
SETL compiles source files into, and loads  bytecode from, specially formatted files called libraries. Each such file contains bytecode representing a collection of named programs, packages, and object classes. The seuence of files searched to find the bytecode needed to execute a prgram is defined by the SETL system's current 'library list'; compilation puts the bytecode which it produces into the first file in the current library list, which is considered to  be the 'active library'. 

The library list can be set using the 'Set  Library List...' option of the SETL IDE's 'Library' menu. It can also be set from within a SETL program by using the 'set_library_list' operation avaialble in IDE_pak, whose string parameter should be a comma-separated list of library file names.

<Rebuild All>

<HELP>
The SETL IDE provides a 'Rebuild All' operation which can be used to reconstuct large SETL libraries of programs, packages, and object classes. This reads a line-organized file called 'makefile', which must be present in the same folder as the IDE itself, and successively compiles all the files listed in 'makefile.'

<events>
	use eventpak;

<HELP>
The SETL eventpak provides basic facilities for connecting SETL to sources of events. One such source of events is the SETL graphic interface itself, but since this can be used directly via its 'tk.mainloop()' call, it does not require eventpak use. However, the eventpak should be used if the SETL graphic interface is to be used with other event sources, for example a voice recognizer.

The eventpak allows single events to be obtained from event sources which return them, and also proivdes event loop objects set up to manage continuing streams of events. Event sources are represented to the eventpak by evt_source_fn objects; These are SETL wrappers around native function objects. Each native event generating package must provide a parameterless function which can be called to obtain such an evt_source_fn object representing its own event stream. For example, the primary graphic interface package Tk.stl provides the function tk_get_event_source_function() for this purpose, and voicepak provides voicepak_get_event_source_function().

To use the eventpak, we first create an event-loop object, and then add event sources to it. Each of these is represented by its evt_source_fn object. A SETL callback fuction is assigned to each such event sourcewhen it is added to the event-loop object. Thes can be removed from the event-loop object when an event stream is to be ignored. Once this has been done, one enters the 'event_mainloop' to get a continuing stream of callbacks, or calls 'event_single' to get a single callback if any is available.

eventpak provides the following routines:

procedure event_create();
		-- create and return an event-loop object
		-- this is the 'evt_inst' appearing in the following calls

procedure event_source_add(evt_inst, evt_source_fn, callback);
		-- register an event source with the 'evt_inst' object; 
		-- this is represented by the evt_source_fn obtained 
		-- from the corresponding native package
		-- it returns an event-source id integer 
		-- which identifies the new event source, for removal if desired

procedure event_remove(evt_inst, evt_id);
		-- remove an event source from the list of registered sources
			
procedure event_mainloop(evt_inst);
		-- enter the main loop, which loops endlessly through the 
		-- list of all registered event sources to handle their events

procedure event_single(evt_inst);
		-- execute a single event; this allows a less efficient but more
		-- flexible event main loop to be programmmed in SETL

<voice recog.>
	use voicepak;

	voicepak_create(string, callback := OM);	-- create a voice recognition object
	voicepak_start_recognize(vp_instance);		-- start voice recognition
	voice_event_source := voicepak_get_event_source_function();
				-- function to be added to an eventpak loop object 

<HELP>
The SETL voicepak allows SETL use of native voice recognition facilities. To use it, one first creates a voice recognition object, and then starts it (it can be suspended subsequently, if desired.) When the voice recognition object is created, a comma-delimited list of phrases to be reconized and returned is passed to it; when any of these phrases is subsequently recognized, an event package consisting of the corresponing string is generated and passed to whatever voice-callback handler has been set up. 

An evt_source_fn object representing the stream of interpreted voice events can be obtained from voicepak and added to an eventpak event-loop object, along with a one-parameter SETL callback-handler routine for these voice events. Detected voice events always generate event package consisting of the character string that was spoken.

voicepak provides the following routines:

procedure voicepak_create(string, callback);	
	-- create a voice recognition object. The 'string' parameter
	-- is a comma-delimited list of phrases to be reconized and returned.
	-- (The Apple voice recognizer does better with long than with
	-- short phrases.) 
	-- voicepak_create returns a vp_instance object to be used in other
	-- calls. If 'callback' is non-OM, it should be a 1-parameter
	-- function, will be called whenever a voice event is detected. 
	-- This is safe only if the voice recognition system
	-- is the only source of asynchronous callbacks. 
	-- Otherwise this callback parameter should be OM, and 
	-- the callback should instead be installed in an event_pak loop object. 
				
procedure voicepak_start_recognize(vp_instance);
				-- start voice recognition

procedure voicepak_stop_recognize(vp_instance);
				-- stop voice recognition
procedure voicepak_idle();
				-- wait for a voice event
procedure voicepak_next_command();
				-- get the next available voice command

procedure voicepak_get_event_source_function();
	-- get the event source function for this package; this is the function 
	-- that must be used in the event package, if that is used

<random>
use random_pak;

handle:= start_random(["A","B","C"], OM);
print([random(handle): n in [1..10]]);
		-- print randomized sequence of 10 letters
print([random(handle): n in [1..10]]);		-- and another such

<HELP>
random_pak provides the two procedures
 
start_random(source,seed);
		-- returns a 'handle', representing a stream of random items

Random(Handle);		-- get next item in a stream of random items

The 'source' in a 'start_random' call can be any of:

1.  An integer n.  The stream consists of integers from 1 to n.
2.  A positive real x.  The stream consists of reals from 0.0 to x.
3.  A set s. The stream consists of random elements of s.
4.  A tuple t. The stream consists of random elements of t.

The 'seed' can be any integer, or OM;  if it is OM the time is used
to generate a starting integer. Use an integer if you want your random selections to be repeatable.

<string_util>
tup_of_tups := breakup(breakup("Jack and Jill;Hot and Cold;Red, White, and Blue",";"),", ");
print(tup_of_tups);
<HELP>
string_utility_pak provides a small library of frequently used string operations in high efficiency native versions. These are:

breakup(obj,chars);		-- cuts a string at any of the indicated characters; 
						-- recursively applicable to tuples of strings
single_out(obj,chars);	-- cuts a string at any of the indicated characters, keeping
						-- them as singletons; 
						-- recursively applicable to tuples of strings
segregate(obj,chars);	-- cuts a string into segments consisting alternately
						-- of characters in/notin 'chars'
						-- recursively applicable to tuples of strings

join(tuple,chars);		-- joins tuple of strings into a string, insterting the string
						-- 'chars' as a separator.

suppress_chars(string,chars);	-- suppress all characters in 'chars', 
								-- returning string of others
keep_chars(string,chars);   	-- keep and return all characters of 'string' 
								-- that belong to 'chars', suppressing others

case_change(string,mode);   	-- change case from upper to lower ofr vide versa,
								-- depending on 'mode', which can be "ul" or "lu"
<red_string_util>
**
<HELP>
red_string_utility_pak extends string_utility_pak with a collection of useful but less frequently used string operations, implemented in SETL; and with a collection of closures which emulates some of SNOBOL's backtracking string-matching capabilities. The operations provided are:

<rx>
**

<HELP>
'rx' is a SETL interface to the native GNU regular expression package; 'rxp' is a SETL class, built on rx and designed to ease its use. The procedures in rx are:

regcomp(rw rx,pattern,flags);
	-- sets rx to the compiled form of the regular expression 'pattern' and returns 0 or an error code
	-- 'flags' is an integer whose bits allow for various special options documented in the rx package. 
regexec(rx,stg,flags,rw pos);	-- runs complied the rx against stg, returning 0 or an error code
	-- if the match succeeds, pos is returned as a tuple defining the way 
	-- in which the whole expression and its subparts were matched. 
	-- 'flags' is an integer whose bits allow for various special options documented in the rx package. 

The operations provided by the class 'rxp' are:

<parser>
program test;
use parser,string_utility_pak;

stg := "program testerr;\na := 0;;\nend a testerr;";
print(compile_with_errs(stg));

procedure compile_with_errs(source);		-- compiles string and returns error vector

	if compile(source) = 0 then return []; end if;
	return [stg(1..#stg - 1): i in [0..setl_num_errors() - 1] | (stg :=  setl_err_string(i)) /= ""];
	
end compile_with_errs;

end test;

<HELP>
The native package 'parser' provides four functions:

parse(stg);		-- returns a representation of the parse tree of stg as a SETL tuple.
  				-- stg can be any SETL expression, loop body, procedure, list of such,
  				-- package body,or class body.
compile(stg);	-- compiles the string stg, returning 0 if compilation succeeds and OM
				-- if it fails. If comilation succeeeds, the  programs, packages, and
				-- classes compiled are entered into the  first library of the current
				-- library list
setl_num_errors()	-- returns the number of errors generated by the last preceding
					-- 'compile' operation
setl_err_string(err_num)	-- setl_err_string(j) returns the j-th error message generated
						 	-- by the last preceding 'compile' operation; 
						 	-- note that indexing is from 0 in  this case, and that
						 	-- each error message begins with the line and character
						 	-- position with which it begins, allowing  error messages to
						 	-- be integrated into the source code to which they refer.
						 	-- This is done by the 'parse' tool.

<stringm>
**

<HELP>
********helptext********

<get_lines>
**

<HELP>
get_lines_pak provides 4 utility input routies and one print utility:

get_lines(file_name);   -- gets all lines in a file, as a tuple of strings
get_file(file_name); 	-- gets an entire file, as one big string
print_set(the_set);
    -- prints tuples and sets element by element, with indentation

read_lines(file_name);  -- reads succession of lines in SETL or line format

read_named_data(name_of_source_file);
-- reads sections of data and lines, named by preceding headers of the form
-- DATA_FOR_data_item_name and DATA_FOR_LINES_data_item_name

<tk>
**

<HELP>
********helptext********
<numerical>
**

<HELP>
********helptext********
<image>
**

<HELP>
********helptext********
<database>
**

<HELP>
********helptext********
<polynomial>
**

<HELP>
********helptext********
<primes>
**

<HELP>
********helptext********
<concordance>
**

<HELP>
********helptext********
<midi>
**

<HELP>
********helptext********
<IDE_pak>
-- see Tools:writing_a_tool for explanation of the way in which IDE_pak is used.

<HELP>
The primitives available via the native package IDE_pak are:

get_buffer();	-- reads the contents of the target edit window of a drag-and-drop operation
get_position();	-- reads the drop position, within a target edit window, of a drag-and-drop operation
get_length();	-- gets length, in characters, of the target edit window of a drag-and-drop operation
set_buffer(from_pos,to_pos,stg);	
	-- replaces indicated section of target edit window contents by indicated string

get_parameter();	-- reads the help-file text section immediately following the tool tag 

get_selection();	-- returns the boundaries of the currently
					-- selected part of the target edit window, as a pair
set_selection(from_pos,to_pos);		-- sets the selection boundaries in the target edit window

<IDE_tools_pak>
-- see Tools:writing_a_tool for explanation of the way in which IDE_pak and IDE_tools_pak are used.

<HELP>
IDE_tools_pak provides a set of utility extensions of the native package IDE_pak. The operations it provides are:

<debug_pak>
**

<HELP>
debug_pak provides several simple but useful and easy-to-use tools for debugging and maintenance testing  of SETL programs,  including facilies for test-coverage assesment and execution profiling.  The procedures and globa vriable provided are  

	var debug_callbacks := {};	
	-- maps labels for which callbacks are to be triggered 
	-- into associated routines callback(label,cycle,history)

	procedure setup_debugs(setup_stg,label_stg); 	
		-- set up label-associated value names and keep-value counts 
	procedure traverse(label,val); 					
		-- note traversal of label and capture value
	procedure debug_snapshot(); 					
		-- debug data printout
	procedure set_repform(label,name,transmap); 	
		-- attaches value transformation routine to specified variable

	procedure must_traverse(label_set); 			
		-- add to set of labels that  must  be traversed
	procedure report_untraversed(); 				
		-- final report on labels traversed
	procedure usage_report(); 						
		-- print terminal report of traversals

<SECTION=Tools>
<using_tools>
use IDE_pak,IDE_tools_pak;		-- other packages can also be used
<HELP>
The tools in this extensible collection are used by dragging them onto an IDE edit window, whose contents they then access, analyze, and (possibly) modify. Some of the tools apply to an entire window or to a preselected part of the window, and so can be dropped anywhere in the window. Others react in a more specific, local manner to the window position at which they are dropped.

Some of the tools provided are:

count_words:		prints list of words appearing in the selected window section, or the whole window

rare: 				prints list of words appearing just once or twice in the selected window section

capitalize: 		capitalizes the selected window section

lower:				un-capitalizes the selected window section

trace: 				inserts code following a procedure header which prints
					parameter values whenever the procedure is called.

show_entries: 		inserts code following a procedure header which 
					displays parameter values in a TK window whenever 
					the procedure is called.

parse: 				parses the selected section of the window, printing an error diagnostic or "OK"

profile: 			after the code in an edit window has  been executed 
					with the "Profiler Dump" and "Debug to File' options  
					both set, this tool will display an execution-time 
					profile of the window, keyed to its source text

debug_setup: 		sets up a program for line-trace debugging and 
					postmortem assertion checking by inserting tracing code

cleanup: 			removes the insertions made by the debug_setup tool

Personal1, etc.		If you supply a program called Personal1, it 
					will be executed when this tag is dragged into an
					edit window, and can acess and modify the window.

<writing_a_tool>
use IDE_pak,IDE_tools_pak;		-- other packages can also be used
<HELP>
IDE 'tools' are SETL programs, executed while SETL programs are being edited, which can access, analyze, and modify the contents of IDE edit windows. The primitives available for this are described by the 'IDE_pak' item of the 'libs' tab in this help window.  Each 'tool' is listed in a help file section of the following form:

	(i)		tool-name 						(within pointed brackets)
	(ii)	tool-parameter-string			can consist of multiple lines
	(iii)	SCRIPT or SCRIPT=program_name	(within pointed brackets)
	(iv)	text of tool program (ignored if SCRIPT=program_name was used) 

Once a tool has  been set up in the format indicated, the tool-parameter-string supplied will be read, and the program P named by 'program_name' will be executed. If the '=program_name' clause has been omitted, then the program text following the SCRIPT tag will be read, compiled into a program P, and executed. (This should be a complete SETL program.)  In either case the tool-parameter-string is available to the program P, as the value of the function 'get_parameter()' supplied by IDE_pak. Note that programs P invoked in this way will normally use IDE_pak, and possibly also the extended set of utility routines available in IDE_tools_pak. 

<count_words>
**
<SCRIPT>
program test;
use ide_pak,extended_SETL_lexer,sort_pak,string_utility_pak,ide_tools_pak;		-- lexer is in rx_pak.stl
abend_trap := wayte;
	buf := get_buffer();
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) = ix2 - ix1 then 		-- trick for 'greater_equal'
		buf := buf(ix1..ix2);
	end if;
	
	print(#(wds := get_tokens(case_change(buf,"ul"))));

	sorted_wds := merge_sort({x: x in wds | #x > 0 and not (x(1) in 
				" 0123456789#:=,./?;'[]=-)(*&^%$#@!~`\n\t\r\"\\|{}+\x3E\x3C") 
							and not x in SETL_reserved_words});
	for x in sorted_wds loop nprint(x ," "); end loop;

procedure wayte(); for j in [1..10000000]  loop x  := j + 1; end loop; end wayte;
end test;
<HELP>
Dropping this on a code window prints the total number of words in the selected section of the window (ignoring comments), along with an alphabetized list of all these words. If nothing has been selected, the whole window is processed.

<rare>
**
<SCRIPT>
program test;
use ide_pak,extended_SETL_lexer,sort_pak,string_utility_pak,ide_tools_pak;		-- lexer is in rx_pak.stl

	buf := get_buffer();
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) = ix2 - ix1 then 		-- trick for 'greater_equal'
		buf := buf(ix1..ix2);
	end if;
	
	wds := get_tokens(case_change(buf,"ul"));
	wds := [x: x in wds | #x > 0 and not (x(1) in 
				" 0123456789#:=,./?;'[]=-)(*&^%$#@!~`\n\t\r\"\\|{}+\x3E\x3C") 
							and not x in SETL_reserved_words];
	numoccs := {};
	for x in wds loop numoccs(x) := (numoccs(x)?0) + 1; end loop;
	
	sorted_wds := merge_sort({x: x in wds | #x /= 0 and not (x(1) in "0123456789") and numoccs(x) = 1 
				and x notin SETL_reserved_words and x notin tk_atts});
	sorted_wds2 := merge_sort({x: x in wds | #x /= 0 and not (x(1) in "0123456789") and numoccs(x) = 2 
				and x notin SETL_reserved_words and x notin tk_atts});

	if #sorted_wds /= 0 then 
		sorted_wds := join(sorted_wds," ");
		print("Words occuring once: ",sorted_wds);
	end if;
	
	if #sorted_wds2 /= 0 then 
		sorted_wds2 := join(sorted_wds2," ");
		print("\nWords occuring twice: ",sorted_wds2);
	end if;

end test;
<HELP>
Dropping this on a code window prints a report on all words occuring just once or twice in the selected section of the window. If nothing has been selected, the whole window is processed.

<procedures>
**
<SCRIPT>
program test;
use ide_pak,string_utility_pak;
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) /= (ix2 - ix1) then [ix1,ix2] := [1,get_length()]; end if;
	for line in breakup(get_buffer()(ix1..ix2),"\r\n") loop 
		span(line," \t"); if #line > (np := #(pr := "procedure")) and line(1..np) = pr then print("--\t" + line); end if;
	end loop;
end test;
<HELP>
Dropping this on a code window produces a list of all the procedures defined in the selected section of the window.

<traceprocs>
**
<SCRIPT>
program test;
use debug_inspect_setup;
	setup_debug_inspect;		-- insert inspection code and compile
end test;
<HELP>
Dropping this on a code window compiles the code in a form incorporating additional trace statements. These statements are selected by initial comments beginning with the special mark "---:". This should be followed by a comma-separated set of marked procedure names. If a procedure name is not otherwise marked, only entries to the procedure will be traced

Trace-code output is generated when a program compiled using this code aborts. 

<showprocs>
**
<SCRIPT>
program test;
use ide_pak,string_utility_pak,tkw;
	var Tk,global_1,global_2,global_3;
	[ix1,ix2] := ide_pak.get_selection();
	if abs(ix2 - ix1) /= (ix2 - ix1) then [ix1,ix2] := [1,get_length()]; end if;
	tup := [];		-- will collect list of procedures
	for line in breakup(get_buffer()(ix1..ix2),"\r\n") loop 
		span(line," \t"); 
		if #line > (np := #(pr := "procedure")) and line(1..np) = pr then 
			break(line," "); span(line," "); name := break(line,"(;"); tup with:= name; 
		end if;
	end loop;
	Tk := tkw(); Tk(OM) := "Procedures Display";						-- create the Tk interpreter
	
	row := 1; col := 1;
	for name in tup loop 
		ckbut := Tk("checkbutton",name); 
		ckbut("row,column") := str(row) + "," + str(col); 
		if (col +:= 1) = 4 then col := 1; row +:= 1; end if;
	end loop;

	Tk.mainloop();		-- enter the Tk main loop

end test;
<HELP>
Dropping this on a code window produces a list of all the procedures defined in the selected section of the window.

<capitalize>
**
<SCRIPT>
program test;
use ide_pak,string_utility_pak;
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) /= (ix2 - ix1) then [ix1,ix2] := [1,get_length()]; end if;
	buffer_part := get_buffer()(ix1..ix2);
	set_buffer(ix1,ix2,case_change(buffer_part,"lu"));
end test;
<HELP>
Dropping this on a code window capitalizes the selected section of the window.

<lower>
**
<SCRIPT>
program test;
use ide_pak,string_utility_pak,red_string_utility_pak;
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) /= (ix2 - ix1) then [ix1,ix2] := [1,get_length()]; end if;
	buffer_part := get_buffer()(ix1..ix2);
	set_buffer(ix1,ix2,case_change(buffer_part,"ul"));
end test;
<HELP>
Dropping this on a code window changes the selected section of the window to lower case. If nothing has been selected, the whole window is processed.
<trace_entry>
**
<SCRIPT>
program test;
use ide_pak,string_utility_pak,ide_tools_pak,red_string_utility_pak,ide_tools_pak;
	
	if (tup := getproc_name_args_linened()) = OM then stop; end if;	-- procedure not found	
	[procname,arglist,eol_loc] := tup;

	line_to_insert := "\rprint(\"**Entry to " + procname + ": \",";
	
	for arg in arglist loop line_to_insert +:= ("\" " + arg + " := \"," + arg + ","); end loop;
	line_to_insert := line_to_insert(1..#line_to_insert - 1) + ");";

	set_buffer(eol_loc,eol_loc - 1,line_to_insert);		-- insert the trace line just before the eol
	
end test;
<HELP>
Dropping this on a procedure header inserts code which prints a report on parameter values whenever the procedure is called.

<show_entries>
**
<SCRIPT>
program test;
use ide_pak,ide_tools_pak,string_utility_pak,red_string_utility_pak;
	
	[procname,arglist,eol_loc] := getproc_name_args_linened();
	lines_to_insert := make_code(procname,arglist);
	set_buffer(eol_loc,eol_loc - 1,lines_to_insert);		-- insert the trace line just before the eol

end test;
<HELP>
Dropping this on a procedure header inserts code which displays the parameter values in a TK window whenever the procedure is called. When this facility is used, the procedure being traced should be called from within a main routine invoked by a Tk event,  possibly a timed event. The following example ilustrates the overall structure that can be used.

program test;	-- test of show_entries tool
	use tkw;		-- use the main widget class

	Tk := tkw(); Tk(OM) := "Caption";	
	
	Tk.createtimer(10,main);	-- start the main program after 1/100 sec.

	Tk.mainloop();		-- enter the Tk main loop
	
	procedure main(ntimes);	
		-- main program, representing a non-interactive SETL run
		-- all other code is called starting from here 
	end main;

end test;
<parse>
**
<SCRIPT>
program test;
use ide_pak,parser;
	[ix1,ix2] := get_selection();
	if abs(ix2 - ix1) = (ix2 - ix1) then 
		buffer_part := get_buffer()(ix1..ix2);
		print(if parse(buffer_part) /= OM then "OK" elseif (ne := setl_num_errors()) =  1 then "1 error in  selected section" else str(ne) + " errors in  selected section" end if);
	end if;
end test;
<HELP>
Dropping this on a code window parses the selected section of the window.
If the section contains no parse errors, the message 'OK' is printed.
Otherwise the number of errors is printed.
<parsewin>
**
<SCRIPT>
program test;
use ide_pak,parser,string_utility_pak;

stg := get_buffer();

compile_showall_errs(stg);

procedure compile_with_errs(source);		-- compiles string and returns error vector

	if compile(source) = 0 then return []; end if;
	return [stg(1..#stg - 1): i in [0..setl_num_errors() - 1] | (stg :=  setl_err_string(i)) /= ""];
	
end compile_with_errs;

procedure compile_showall_errs(stg);		-- compiles string and returns source code with all error messages embedded 
	if (errvect := compile_with_errs(stg)) = [] then print("OK, no compile errors."); end if;			-- null string if no errors
	
	source_lines := breakup(stg,"\n\r");		-- now merge the source code with the error message list
	nsourcelines_printed := 0;					-- number of source lines already printed
	with_errors := "";							-- collection of lines with errors
	nc := #stg;									-- total number of characters in window
	
	for msg in errvect loop

		match(msg,"["); lno := break(msg,":"); match(msg,":"); charno := break(msg,":");		-- get line and character number
		lno := unstr(lno); charno := unstr(charno); 
		for j in [nsourcelines_printed + 1..lno min #source_lines] loop with_errors +:= (source_lines(j) + "\r"); end loop;
		with_errors +:= (((charno - 1) max 0) * " " + "^....\r");
		nsourcelines_printed := lno;
	end loop;

	for j in [nsourcelines_printed + 1..#source_lines] loop with_errors +:= (source_lines(j) + "\r"); end loop;
	set_buffer(1,nc,with_errors);

end compile_showall_errs;

end test;
<HELP>
Dropping this on a code window parses the entire window. If there are 
no parse errors, the message 'OK' is printed. Otherwise error indications are
inserted at appropriate positions  in the window. These inserted lines can
be removed by dropping  the 'cleanup' tool on the window.

<parse_cleanup>
**
<SCRIPT>
program test;
use ide_pak,parser,string_utility_pak;

	lines := breakup(stg := get_buffer(),"\n\r");
	cleaned := [];			-- will collect  teh cleaned lines
	
	for  line in  lines loop
		orig_line  := line;
		span(line," "); match(line,"^...."); if line = "" then  continue; end if;
		cleaned with:= orig_line;
	end loop;
	set_buffer(1,#stg,"" +/ [line + "\r": line in  cleaned]);
	
end test;
<HELP>
Dropping this on a code window removes all error-indication lines
inserted by the 'parsewin' tool.  

<profile>
**
<SCRIPT>
program test;			-- test program for display of trace data
	use IDE_pak,IDE_tools_pak;
	
	stg := get_buffer();
	file_handle := open("junk","TEXT-OUT");
	printa(file_handle,stg);
	close(file_handle);
	
	while stg /= "" loop

		span(stg,"\t\r \n");	-- skip whitespace
		ma := match(stg,"--");

		if ma /= "" then continue; end if;		-- ship comments
	
		ma := match(stg,"program");

		if ma = "" then 
			print("**** CANNOT FIND NAME OF PROGRAM ****"); stop; 
		else
			span(stg,"\t\r \n");	-- skip whitespace
			uname := break(stg,"\t\r \n(;");
			exit;
		end if;

	end loop;
print("Here: ",uname);
--	compile_and_run("untitled1.stl");			-- this primitive would be better
--	display_trace("test,untitled1.stl","setl2.dbg"); 		-- display trace of specified units from specified file
	display_trace(uname + ",junk","setl2.dbg"); 	-- display trace of target program

end test;
<HELP>
If the code in an edit window has just been executed with the "Profiler Dump" and "Debug to File' options both set, then dropping this tag on the window will display an execution-time profile of the window, keyed to its source text.

<debug_watch>
use string_utility_pak;
var debug_count := 0,debug_watch_start := OM, debug_watch,debug_captions;			-- globals for debug; move to start of program
abend_trap := rerun; run;

procedure rerun; 		-- program re_execution after crash
	debug_count := 0; debug_watch_start := debug_count - 5; abend_trap := watch_trap;
	run;
end rerun;

procedure watch_trap; 		-- debug info dump procedure 
	if is_integer(debug_watch) then 
		print("Failed on cycle: ",debug_watch);
	else
		debug_captions := breakup(debug_captions,","); 
		print("Failed at count: ",debug_count," at location ",debug_captions(1)); 
		for x = debug_watch(j) loop print(debug_captions(j + 1)?"Value",": ",x); end loop;
	end if;
end watch_trap;

procedure run;			-- wrapper  for main body of program being debugged
--	debug_captions := "place,a,b,c"; 		-- list  of variable names; insert this and following at program points being watched
--	if (debug_count +:= 1) > (debug_watch_start?debug_count) then debug_watch := [a,b,c]; else debug_watch := debug_count; end if;
	 -- Example: 
	 for j in [1..1000] loop

debug_captions := "loc1,j,n"; 		-- this point is being watched
if (debug_count +:= 1) > (debug_watch_start?debug_count) then debug_watch := [j,n]; else debug_watch := debug_count; end if;
		n := 10000/(j - 777);	-- this point is being watched

debug_captions := "loc2,j,m,n"; 	-- this point is being watched
if (debug_count +:= 1) > (debug_watch_start?debug_count) then debug_watch := [j,m,n]; else debug_watch := debug_count; end if;
		m := 10000/(j - 773 - n);	-- this point is also being watched
	 end loop;
end run;

<HELP>
This tool realizes a simple, print-like debugging facility, which is however more sophisticated than the conventional 'insert print statements' technique. It runs a program to be debugged twice, the first time to determine the cycle number at which the program fails. After this the program is automatically re-executed, during which phase more detailed information is collected  and printed out when  the program crashes for a second time. To make this possible, the code inserted by the tool manipulates SETL's global 'abend_trap' variable. Using it also requires that a few stereotyped code lines, of which prototypes are supplied by the tool, be inserted manually in the program being debugged.

The 'debug_watch' keyword should be dragged to the start of the program being debugged, just after any initial declarations. This inserts a few global variable declarations, along with one 'main program' line and a few short auxiliary routines.  The original main program of the code being debugged should then be wrapped as a procedure called 'run', for which the toool supplies header and trailer lines (and a smple body, which should be removed). Trace-dode insertions like those supplied by the tool should  be manually adapted in the obvious way and inserted at each of the code points to be watched during debugging.

The tool supplies a program complete except for its header and trailer lines. This sample program can be insered oin an  empty window and executed directly to see the detailed post-mortem dump produced.   

<debug_setup>
parameter
<SCRIPT>
program test;
	use IDE_tools_pak;		-- 
	
	setup_debug(); 		-- set up the debug insertions
end test;

<HELP>
This tool sets up a program for line-trace debugging and postmortem assertion checking by inserting numbered trace-lines into it.

<debug_cleanup>
parameter
<SCRIPT>
program test;
	use IDE_tools_pak;		-- 
	cleanup_debug();		-- remove the insertions made by the debug_setup tool
end test;

<HELP>
This tool removes the insertions made by the debug_setup tool.

<Personal1>
ANY PARAMETER STRING YOU LIKE
<SCRIPT=Personal1>
<HELP>
The program called Personal1 which you compile will be called when this tag is dropped on a code window. Your program can use the IDE_pak procedures.

<Personal2>
ANY PARAMETER STRING YOU LIKE
<SCRIPT=Personal2>
<HELP>
The program called Personal2 which you compile will be called when this tag is dropped on a code window. Your program can use the IDE_pak procedures.

<Personal3>
ANY PARAMETER STRING YOU LIKE
<SCRIPT=Personal3>
<HELP>
The program called Personal3 which you compile will be called when this tag is dropped on a code window. Your program can use the IDE_pak procedures.

<Personal4>
ANY PARAMETER STRING YOU LIKE
<SCRIPT=Personal4>
<HELP>
The program called Personal4 which you compile will be called when this tag is dropped on a code window. Your program can use the IDE_pak procedures.

<Personal5>
ANY PARAMETER STRING YOU LIKE
<SCRIPT>
program test;                        -- SETL interactive interface example 1
     use ide_pak;
     print("parameter: ",get_parameter());
end test;
<HELP>
This is just for testing.

<De_mix>
**
<SCRIPT>
program test;						-- test of routines for demixing mixed syntax
	use ide_pak,de_mix_pak;

	stg := de_mix(orig := get_buffer()); set_buffer(1,#orig,stg);		-- apply the demix function to the whole buffer
	
end test;

<HELP>
Converts string in mixed SETL/strings syntax into plain SETL

<HTML-setup>
**
<SCRIPT>
program test;
use ide_pak,extended_SETL_lexer,sort_pak,string_utility_pak,ide_tools_pak;		-- lexer is in rx_pak.stl
	-- this requires sort_pak,string_utility_pak,ide_pak,rx,red_string_utility_pak,get_lines_pak,extended_SETL_lexer,(from rx_pak.stl),ide_tools_pak,name_change,and tkw. (name_change is in ide_tools_pak)
--use sort_pak,string_utility_pak,rx,ide_pak,red_string_utility_pak,get_lines_pak,extended_SETL_lexer,tkw,ide_tools_pak,name_change;
	const bo := "\x3CB\x3E", boe := "\x3C/B\x3E"; 		-- bold and bold ends

	buf := get_buffer();
 
	pieces := segregate(buf,"abcdefghijklmnopqurstuwxyz_ABCDEFGHIJKLMNOPQURSTUWXYZ0123456789");
	pieces := [if piece in SETL_reserved_words and x notin tk_atts then bo + piece + boe else piece end if: piece in pieces];
	pieces := [if x(1) = "\t" then 4 * #x * " " else x end if: x in  segregate("" +/ pieces,"\t")];
	pieces := segregate("" +/ pieces,boe);		-- now remove double bolds
	pieces := [piece: piece = pieces(j) | not  ((j > 1 and piece = bo and pieces(j - 1) = " " and pieces(j - 2) = boe)  or (piece = boe and pieces(j + 1) = " " and pieces(j + 2) = bo))];

	print("" +/ [debold_comment(line) + "\n": line  in breakup("" +/ pieces,"\n\r")]);
	
	procedure debold_comment(line); [text,comment] := breakout_comment(line); return text + debold(comment); end debold_comment;
	procedure debold(stg); 
		pieces := segregate(stg,boe); return  "" +/ [piece in pieces | piece /= bo and piece  /= boe];
	end debold;
	
	procedure breakout_comment(stg); 
		tail := rbreak(stg,"-"); if rmatch(stg,"--") /= ""  then return [stg,"--" + tail]; end if;
		while stg /= "" loop
			rmatch(stg,"-"); tail := "-" + tail; 
			tail2 := rbreak(stg,"-"); tail := tail2 + tail;
			if rmatch(stg,"--") /= ""  then return [stg,"--" + tail2 + tail]; end if;
		end  loop;
		
		return [tail,""];
		
	end breakout_comment;
	
	
end test;
<HELP>
Prints version of code in window suitable for HTML display.

<HTML-head>
**
<SCRIPT>
program test;
	use IDE_pak,IDE_tools_pak,string_utility_pak;	
	stg := "`HTML>\r`HEAD>\r`TITLE>Untitled`/TITLE>\r`/HEAD>\r`SCRIPT>\r\r`/SCRIPT> \r`BODY>\r\r`/BODY>\r`/HTML>\r";
	set_buffer(1,0,join(breakup(stg,"`"),"\x3C"));
end test;
<HELP>
Inserts HTML Boilerplate into window.

<HTML-table>
**
<SCRIPT>
program test;
	use IDE_pak,IDE_tools_pak,string_utility_pak;	
	stg := "\r`TABLE BORDER='1' CELLPADDING='1' CELLSPACING='1' WIDTH='1'>\r\t`CAPTION>Caption`/CAPTION>\r\t`TH>Header1`/TH>`TH>Header2`/TH>`TH>Header3`/TH>\r\t`TR>`TD>Item1a`/TD> " + "`TD>Item1b`/TD>`TD>Item1c`/TD>`/TR>\r\t`TR>`TD>Item2a`/TD>`TD>Item2b`/TD>`TD>Item2c`/TD>`/TR>\r\t`TR>" +  "`TD>Item3a`/TD>`TD>Item3b`/TD>`TD>Item3c`/TD>`/TR>\r\t`TR>`TD>Item4a`/TD>`TD>Item4b`/TD>`TD>Item4c`/TD> `/TR>\r`/TABLE>\r\r";
	i := get_position();
	set_buffer(i,i - 1,join(breakup(stg,"`"),"\x3C"));
end test;
<HELP>
Inserts sample HTML table at drop-point.

<standardize_types>
**
<SCRIPT>
program test;		-- converts all files in list to creator type and file type of first file in the list
	use net_utilities,ide_pak,string_utility_pak;

					-- get lines in SETL edit window and Macintosh kind-codes for first file
	[creator,ftype] := file_kind((files := breakup(get_buffer(),"\n\r"))(1));

					-- set same  kind-codes for every other file in list
	for file in files(2..) loop file_set_creator_type(file,creator,ftype); end loop;
end test;
<HELP>
Converts all files in list to creator type and file type of first file in the list

<frames>
**
<SCRIPT>
program test;
	use IDE_pak,IDE_tools_pak,string_utility_pak;	
	stg := "`FRAMESET ROWS='30*30%,*'>\r\t`FRAME SRC='file1' NAME='framename1' MARGINWIDTH='5' MARGINHEIGHT='5' SCROLLING=AUTO>\r\t`FRAME SRC='file2' NAME='framename2' MARGINWIDTH='5' MARGINHEIGHT='5' SCROLLING=AUTO>\r`/FRAMESET>";
	set_buffer(1,0,join(breakup(stg,"`"),"\x3C"));
end test;
<HELP>
Inserts HTML Frameset Boilerplate into window.

<make_reveal>
**
<SCRIPT>
program test;
	use IDE_pak,IDE_tools_pak,string_utility_pak;	
	lines := breakup(get_buffer(),"\r\n");
	buf_len := get_length();
	rev_text := "rev_text := \"" +  join(lines,"\\n\" + \r\t\t\"") + "\";";
	set_buffer(1,buf_len,rev_text);
end test;
<HELP>
Converts  a piece of text to a reveal-text constant.
<encyclopedia>
**
<SCRIPT>
program test;
	use IDE_pak,IDE_tools_pak,encyclopedia_pak,string_utility_pak;	
	buf := get_buffer();
	[i,j] := get_selection();

	if not j >= i then 
		set_buffer(#buf + 1,#buf,"\r\r********* Nothing has been selected *********"); 
	else
		selstg := case_change(buf(i..j),"ul"); selstg(1) := case_change(selstg(1),"lu");
		
		if selstg(1) notin "0123456789" then 		-- should be at  least a  triple  of letters
			if 3 > #selstg then 
				set_buffer(#buf + 1,#buf,"\r\r********* Selection is  too  short *********"); 
			else
				set_buffer(1,#buf,if (ar := arrange(selstg)) = "" then buf + "\rNo entries" else selstg + "\r\r" + ar end if);
			end if;
		else			-- should be all digits
		
			selsdigs := span(selstg,"0123456789");
			j := unstr(selsdigs);		-- convertto integer
			
			if j = 0 then  
				set_buffer(#buf + 1,#buf,"\r\r********* Selection is  ZERO *********"); 
			else
				buflines := breakup(buf,"\n\r");
				url := show_url(buflines(1),j);
				set_buffer(1,#buf,buf + "\r" + url);
			end if;
		end if;
		
	end if;

end test;
<HELP>
Accesses encyclopedia

<SECTION=Build>
<program>
program X1;
	X;
end X1;
<HELP>

<procedure>

	procedure X1(X);
		X;
	end X1;
<HELP>

<package>
package X1(X);
	procedure X2(X3);
end X1;
package body X1(X);
	procedure X2(X3);
		X;
	end X2;
end X1;
<HELP>

<class>
class X1(X);
	procedure X2;
end X1;
class body X1(X);
	procedure X2;
		X;
	end X2;
end X1;
<HELP>

<X + X>
X + X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X + X)>
(X + X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X - X>
X - X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X - X)>
(X - X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X * X>
X * X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X * X)>
(X * X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X / X>
X / X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X / X)>
(X / X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X ** X>
X ** X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X ** X)>
(X ** X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X mod X>
X mod X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X mod X)>
(X mod X)
<SCRIPT=replace_the_placeholder>
<HELP>

<-X>
-X
<SCRIPT=replace_the_placeholder>
<HELP>

<-(X)>
-(X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X and X>
X and X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X and X)>
(X and X)
<SCRIPT=replace_the_placeholder>
<HELP>

<X or X>
X or X
<SCRIPT=replace_the_placeholder>
<HELP>

<(X or X)>
(X or X)
<SCRIPT=replace_the_placeholder>
<HELP>

<not X>
not X
<SCRIPT=replace_the_placeholder>
<HELP>

<not (X)>
not (X)
<SCRIPT=replace_the_placeholder>
<HELP>

<ifthen;>
if X then
	X;
else
	X;
end if;
<SCRIPT=replace_the_placeholder>
<HELP>

<ifexp>
if X then X else X end if
<SCRIPT=replace_the_placeholder>
<HELP>

<for>
for X loop
	X;
end loop;
<HELP>

<=>
X = X
<SCRIPT=replace_the_placeholder>
<HELP>

<:=>
X := 
<HELP>

<+:=>
X +:= 
<HELP>

<-:=>
X -:= 
<HELP>

<with:=>
X with:= 
<HELP>

<less:=>
X less:= 
<HELP>

<print>
print(X); 
<SCRIPT=replace_the_placeholder>
<HELP>

<(X)>
(X) 
<SCRIPT=replace_the_placeholder>
<HELP>

<,X>
,X 
<HELP>

<;>
; 
<HELP>

<f(X)>
X(X)
<SCRIPT=replace_the_placeholder>
<HELP>

<[x:]>
[X: X]
<SCRIPT=replace_the_placeholder>
<HELP>

<{x:}>
{X: X}
<SCRIPT=replace_the_placeholder>
<HELP>

<forin>
X in X
<SCRIPT=replace_the_placeholder>
<HELP>

<for=>
X = X(X)
<SCRIPT=replace_the_placeholder>
<HELP>

<|>
 | X
<HELP>

<[..]>
[X..X]
<SCRIPT=replace_the_placeholder>
<HELP>

<{..}>
{X..X}
<SCRIPT=replace_the_placeholder>
<HELP>

<exists>
exists X | X
<SCRIPT=replace_the_placeholder>
<HELP>

<forall>
forall X | X
<SCRIPT=replace_the_placeholder>
<HELP>

<vary>
blah
<SCRIPT=replace_the_token>
<HELP>

<test>
blah
<SCRIPT>
program test; 
	use ide_pak; 
	stg := get_buffer(); [lo,hi] := get_selection(); set_buffer(lo,hi,get_parameter()); 
end test;
<HELP>

<SECTION=Unix>
<alias>

<HELP>
Create or remove a pseudonym or shorthand for a command or series of commands 

<apropos>

<HELP>
locate commands by keyword lookup

<at>

<HELP>
Execute commands at a later time

<atq>

<HELP>
Display the jobs queued to run at specified times


<atrm>

<HELP>
Remove jobs spooled by at or batch


<awk>

<HELP>
 Pattern scanning and processing language


<bdiff>

<HELP>
 Big diff


<cancel>

<HELP>
Send/cancel requests to an LP print service

<cat>

<HELP>
Concatenate and display files

<cd>

<HELP>
Change working directory

<chgrp>
 Change file group ownership

<HELP>

<alias>
chkey           chkey (1)       - change user's secure RPC key pair
chmod           chmod (1)       - change the permissions mode of a file
chmod           chmod (2)       - change access permission mode of file
chmod           chmod (1)       - change the access permissions of files
chown           chown (1)       - change file ownership
chown           chown (1b)      - change owner
chrtbl          chrtbl (1m)     - generate character classification and conversion tables
ckgid           ckgid (1)       - prompts for and validates a group id
clear           clear (1)       - clear the terminal screen
cmp             cmp (1)         - compare two files
col             col (1)         - reverse line-feeds filter
colltbl         colltbl (1m)    - create string collation routines
comm            comm (1)        - select or reject lines common to two files
comm            comm (1)        - compare two sorted files line by line
command         command (1)     - execute a simple command
compress        compress (1)    - compress, uncompress files or display expanded files
cp              cp (1)          - copy files

<HELP>



<END>
acctcom         acctcom (1)     - search and print process accounting files
adb             adb (1)         - general-purpose debugger
addbib          addbib (1)      - create or extend a bibliographic database
admintool       admintool (1m)  - system administration with a graphical user interface
aliasadm        aliasadm (1m)   - manipulate the NIS+ aliases map
arch            arch (1)        - display the architecture of the current host
asa             asa (1)         - convert FORTRAN carriage-control output to printable form
audioconvert    audioconvert (1)    - convert audio file formats
audioplay       audioplay (1)   - play audio files
audiorecord     audiorecord (1) - record an audio file
banner          banner (1)      - make posters
basename        basename (1)    - deliver portions of path names
basename        basename (1b)   - display portions of pathnames
basename        basename (3g)   - return the last element of a path name
basename        basename (1)    - strip directory and suffix from filenames
batch           at (1)          - execute commands at a later time
bc              bc (1)          - arbitrary precision arithmetic language
cachefsstat     cachefsstat (1m)    - Cache File System statistics
cal             cal (1)         - display a calendar
calendar        calendar (1)    - reminder service
captoinfo       captoinfo (1m)  - convert a termcap description into a terminfo description
cat             cat (1)         - concatenate files and print on the standard output
catman          catman (1m)     - create the cat files for the manual
checkeq         eqn (1)         - typeset mathematics test
checknr         checknr (1)     - check nroff and troff input files; report possible errors
chown           chown (1m)      - change owner
chown           chown (2)       - change owner and group of a file
chown           chown (1)       - change the user and group ownership of files
ckdate          ckdate (1)      - prompts for and validates a date
ckint           ckint (1)       - display a prompt; verify and return an integer value
ckitem          ckitem (1)      - build a menu; prompt for and return a menu item
ckkeywd         ckkeywd (1)     - prompts for and validates a keyword
ckpath          ckpath (1)      - display a prompt; verify and return a pathname
ckrange         ckrange (1)     - prompts for and validates an integer
ckstr           ckstr (1)       - display a prompt; verify and return a string answer
cksum           cksum (1)       - write file checksums and sizes
cksum           cksum (1)       - checksum and count the bytes in a file
cktime          cktime (1)      - display a prompt; verify and return a time of day
ckuid           ckuid (1)       - prompts for and validates a user ID
ckyorn          ckyorn (1)      - prompts for and validates yes/no
clear           curs_clear (3x) - clear all or part of a curses window
cp              cp (1)          - copy files
cpio            cpio (1)        - copy file archives in and out
cpio            cpio (1)        - copy files to and from archives
crontab         crontab (1)     - user crontab file
crypt           crypt (1)       - encode or decode a file
crypt           crypt (3c)      - generate encryption
csh             csh (1)         - shell command interpreter with a C-like syntax
csplit          csplit (1)      - split  files based on context
csplit          csplit (1)      - split a file into sections determined by context lines
ct              ct (1c)         - spawn login to a remote terminal
ctags           ctags (1)       - create a tags file for use with ex and vi
cu              cu (1c)         - call another UNIX system
cut             cut (1)         - cut out selected fields of each line of a file
cut             cut (1)         - remove sections from each line of files
date            date (1)        - write the date and time
date            date (1)        - print or set the system date and time
dc              dc (1)          - desk calculator
dd              dd (1m)         - convert and copy a file
dd              dd (1)          - convert a file while copying it
deroff          deroff (1)      - remove nroff/troff, tbl, and eqn constructs
devattr         devattr (1m)    - lists device attributes
devfree         devfree (1m)    - release devices from exclusive use
devreserv       devreserv (1m)  - reserve devices for exclusive use
df              df (1b)         - display status of disk space on file systems
df              df (1m)         - report number of free disk blocks and files
df              df (1)          - summarize free disk space
diff            diff (1)        - display line-by-line differences between pairs of text files 
diff3           diff3 (1)       - 3-way differential file comparison
diffmk          diffmk (1)      - mark differences between versions of a troff input file
dig             dig (1)         - send domain name query packets to name servers
dircmp          dircmp (1)      - directory comparison
dirname         basename (1)    - deliver portions of path names
dirname         dirname (3g)    - report the parent directory name of a file path name
dirname         dirname (1)     - strip non-directory suffix from file name
disable         enable (1)      - enable/disable LP printers
dispgid         dispgid (1)     - displays a list of all valid group names
dispuid         dispuid (1)     - displays a list of all valid user names
dmesg           dmesg (1m)      - collect system diagnostic messages to form error log
dnsquery        dnsquery (1)    - query domain name servers using resolver
domainname      domainname (1m) - set or display name of the current domain
dos2unix        dos2unix (1)    - convert text file from DOS format to ISO format
du              du (1b)         - display the number of disk blocks used per directory or file
du              du (1m)         - summarize disk usage
du              du (1)          - summarize disk usage
dumpcs          dumpcs (1)      - show codeset table for the current locale
dumpkeys        loadkeys (1)    - load and dump keyboard translation tables
echo            curs_inopts (3x)    - curses terminal input option control routines
echo            echo (1)        - echo arguments 
echo            echo (1b)       - echo arguments to standard output
echo            echo (1f)       - put string on virtual output
echo            echo (1)        - display a line of text
ed              ed (1)          - text editor
edit            edit (1)        - text editor (variant of ex for casual users)
egrep           egrep (1)       - search a file for a pattern using full regular expressions
egrep           grep (1)        - print lines matching a pattern
eject           eject (1)       - eject media such as CD-ROM and floppy from drive
enable          enable (1)      - enable/disable LP printers
env             env (1)         - set environment for command invocation
env             env (1)         - run a program in a modified environment
eqn             eqn (1)         - typeset mathematics test
ex              ex (1)          - text editor
expand          expand (1)      - expand TAB characters to SPACE characters, and vice versa
expand          expand (1)      - convert tabs to spaces
expr            expr (1)        - evaluate arguments as an expression
expr            expr (1b)       - evaluate arguments as a logical, arithmetic, or string expression
expr            expr (1)        - evaluate expressions
exstr           exstr (1)       - extract strings from source files
factor          factor (1)      - obtain the prime factors of a number
false           true (1)        - provide truth values
false           false (1)       - do nothing, unsuccessfully
fc              history (1)     - process command history list
fdetach         fdetach (1m)    - detach a name from a STREAMS-based file descriptor
fdetach         fdetach (3c)    - detach a name from a STREAMS-based file descriptor
fdformat        fdformat (1)    - format floppy diskette or PCMCIA memory card
fg              jobs (1)        - control process execution
fgrep           fgrep (1)       - search a file for a character string
fgrep           grep (1)        - print lines matching a pattern
file            file (1)        - determine file type
file            file (1b)       - determine the type of a file by examining its contents
find            find (1)        - find files
find            find (1)        - search for files in a directory hierarchy
finger          finger (1)      - display information about local and remote users
fmli            fmli (1)        - invoke FMLI
fmt             fmt (1)         - simple text formatters
fmt             fmt (1)         - simple optimal text formatter 
fmtmsg          fmtmsg (1)      - display a message on stderr or system console
fmtmsg          fmtmsg (3c)     - display a message on stderr or system console
fnattr          fnattr (1)      - Update and examine attributes associated with an FNS named object
fnbind          fnbind (1)      - Bind a reference to an FNS name
fncreate_printer                fncreate_printer (1m)   - create new printers in the FNS namespace
fnlist          fnlist (1)      - Display the names and references bound in an FNS context
fnlookup        fnlookup (1)    - Display the reference bound to an FNS name
fnrename        fnrename (1)    - Rename the binding of an FNS name
fnunbind        fnunbind (1)    - Unbind the reference from an FNS name
fold            fold (1)        - filter for folding lines
fold            fold (1)        - wrap each input line to fit in specified width
ftp             ftp (1)         - file transfer program
fusage          fusage (1m)     - disk access profiler
gcore           gcore (1)       - get core images of running processes
gencat          gencat (1)      - generate a formatted message catalog
getconf         getconf (1)     - get configuration values
getdev          getdev (1m)     - lists devices based on criteria
getdgrp         getdgrp (1m)    - lists device groups which contain devices that match criteria
getent          getent (1m)     - get entries from administrative database
getfacl         getfacl (1)     - display discretionary file information
getopt          getopt (1)      - parse command options
getopt          getopt (3c)     - get option letter from argument vector
getopts         getopts (1)     - parse utility options
gettext         gettext (1)     - retrieve text string from message database
gettext         gettext (3i)    - message handling functions
gettxt          gettxt (1)      - retrieve a text string from a message database
gettxt          gettxt (3c)     - retrieve a text string
getvol          getvol (1m)     - verifies device accessibility
graph           graph (1)       - draw a graph
grep            grep (1)        - search a file for a pattern
grep            grep (1)        - print lines matching a pattern
groups          groups (1)      - print group membership of user
groups          groups (1b)     - display a user's group memberships
groups          groups (1)      - print the groups a user is in
hash            hash (1)        - evaluate the internal hash table of the  contents of directories
head            head (1)        - display first few lines of files
head            head (1)        - output the first part of files
host            host (1)        - look up host names using domain server
hostid          hostid (1)      - print the numeric identifier of the current host
hostname        hostname (1)    - set or print name of current host system
hostname        hostname (1)    - set or print the name of the current host system
hostname        hostname (5)    - host name resolution description
hostname        hostname (7)    - host name resolution description
i286            machid (1)      - get processor type truth value
i386            machid (1)      - get processor type truth value
i486            machid (1)      - get processor type truth value
i860            machid (1)      - get processor type truth value
iAPX286         machid (1)      - get processor type truth value
iconv           iconv (1)       - code set conversion utility
iconv           iconv (3)       - code conversion function
iconv           iconv (5)       - code set conversion tables
id              id (1m)         - return user identity
id              ipi (7d)        - IPI driver
id              id (1)          - print real and effective UIDs and GIDs
indxbib         indxbib (1)     - create an inverted index to a bibliographic database
infocmp         infocmp (1m)    - compare or print out terminfo descriptions
iostat          iostat (1m)     - report I/O statistics
ipcrm           ipcrm (1)       - remove a message queue, semaphore set, or shared memory ID
ipcs            ipcs (1)        - report inter-process communication facilities status
jobs            jobs (1)        - control process execution
join            join (1)        - relational database operator
join            join (1)        - join lines of two files on a common field
kbd             kbd (1)         - manipulate the state of keyboard or display the type of keyboard 
kdestroy        kdestroy (1)    - destroy Kerberos tickets
keylogin        keylogin (1)    - decrypt and store secret key with keyserv
keylogout       keylogout (1)   - delete stored secret key with keyserv
kill            kill (1)        - terminate or signal processes 
kill            kill (2)        - send a signal to a process or a group of processes
kinit           kinit (1)       - Kerberos login utility
klist           klist (1)       - list currently held Kerberos tickets
ksh             ksh (1)         - KornShell, a standard/restricted command and programming language
ksrvtgt         ksrvtgt (1)     - fetch and store Kerberos ticket-granting ticket using a service key
last            last (1)        - display login and logout information about users and terminals
lastcomm        lastcomm (1)    - display the last commands executed, in reverse order
ldd             ldd (1)         - list dynamic dependencies of executable files or shared objects
line            line (1)        - read one line
line            plot (3)        - graphics interface
listdgrp        listdgrp (1m)   - lists members of a device group
listusers       listusers (1)   - list user login information
ln              ln (1)          - make hard or symbolic links to files
ln              ln (1b)         - make hard or symbolic links to files
ln              ln (1)          - make links between files
loadkeys        loadkeys (1)    - load and dump keyboard translation tables
locale          locale (1)      - get locale-specific information
locale          locale (5)      -  subset of a user's environment that depends on language and cultural conventions
localedef       localedef (1)   - define locale environment
logger          logger (1)      - add entries to the system log
logger          logger (1b)     - add entries to the system log
login           login (1)       - sign on to the system
logins          logins (1m)     - list user and system login information
logname         logname (1)     - return user's login name
logname         logname (1)     - print user's login name
look            look (1)        - find words in the system dictionary or lines in a sorted list
lookbib         lookbib (1)     - find references in a bibliographic database
lp              lp (1)          - send/cancel requests to an LP print service
lp              lp (7d)         - driver for parallel port
lpstat          lpstat (1)      - print information about the status of the LP print service
ls              ls (1)          - list contents of directory
ls              ls (1b)         - list the contents of a directory
ls              ls (1)          - list contents of directories
mach            mach (1)        - display the processor type of the current host
mail            mail (1)        - read mail or send mail to users
mail            mailx (1)       - interactive message processing system
mailcompat      mailcompat (1)  - provide SunOS compatibility for Solaris mailbox format
mailstats       mailstats (1)   - print statistics collected by sendmail
mailx           mailx (1)       - interactive message processing system
makedev         makedev (3c)    - manage a device number
man             man (1)         - find and display reference manual pages
man             man (5)         - macros to format Reference Manual pages
mconnect        mconnect (1)    - connect to SMTP mail server socket
mesg            mesg (1)        - permit or deny messages
mkdir           mkdir (1)       - make directories
mkdir           mkdir (2)       - make a directory
mkdir           mkdir (1)       - make directories
mkfifo          mkfifo (1m)     - make FIFO special file
mkfifo          mkfifo (3c)     - create a new FIFO
mkfifo          mkfifo (1)      - make FIFOs (named pipes)
mkmsgs          mkmsgs (1)      - create message files for use by gettxt
montbl          montbl (1m)     - create monetary database
more            more (1)        - browse or page through a text file
mpstat          mpstat (1m)     - report per-processor statistics
msgfmt          msgfmt (1)      - create a message object from a message file
mt              mt (1)          - magnetic tape control
mt              mt (7d)         - tape interface
mt              mt (1)          - control magnetic tape drive operation
mv              mv (1)          - move files
mv              mv (1)          - rename files
nawk            nawk (1)        - pattern scanning and processing language
neqn            eqn (1)         - typeset mathematics test
netstat         netstat (1m)    - show network status
newaliases      newaliases (1)  - rebuild the data base for the mail aliases file
newform         newform (1)     - change the format of a text file
newgrp          newgrp (1)      - log in to a new group
news            news (1)        - print news items
nfsstat         nfsstat (1m)    - NFS statistics
nice            nice (1)        - invoke a command with an altered scheduling priority
nice            nice (2)        - change priority of a process
nice            nice (3b)       - change priority of a process
nice            nice (1)        - run a program with modified scheduling priority
nisaddcred      nisaddcred (1m) - create NIS+ credentials
niscat          niscat (1)      - display NIS+ tables and objects
nischgrp        nischgrp (1)    - change the group owner of a NIS+ object
nischmod        nischmod (1)    - change access rights on a NIS+ object
nischown        nischown (1)    - change the owner of a NIS+ object
nischttl        nischttl (1)    - change the time to live value of a NIS+ object
nisdefaults     nisdefaults (1) - display NIS+ default values
niserror        niserror (1)    - display NIS+ error messages
nisgrep         nismatch (1)    - utilities for searching NIS+ tables
nisgrpadm       nisgrpadm (1)   - NIS+ group administration command
nisln           nisln (1)       - symbolically link NIS+ objects
nisls           nisls (1)       - list the contents of a NIS+ directory
nismatch        nismatch (1)    - utilities for searching NIS+ tables
nismkdir        nismkdir (1)    - create NIS+ directories
nispasswd       nispasswd (1)   - change NIS+ password information
nisrm           nisrm (1)       - remove NIS+ objects from the namespace
nisrmdir        nisrmdir (1)    - remove NIS+ directories
nistbladm       nistbladm (1)   - NIS+ table administration command
nistest         nistest (1)     - return the state of the NIS+ namespace using a conditional expression
nl              curs_outopts (3x)   - curses terminal output option control routines
nl              nl (1)          - line numbering filter
nl              nl (1)          - number lines of files
nohup           nohup (1)       - run a command immune to hangups
nohup           nohup (1)       - run a command immune to hangups, with output to a non-tty
nroff           nroff (1)       - format documents for display or line-printer
nslookup        nslookup (1m)   - query name servers interactively
nslookup        nslookup (1m)   - query Internet name servers interactively
nslookup        nslookup (8)    - query Internet name servers interactively
od              od (1)          - octal dump
od              od (1)          - dump files in octal and other formats
on              on (1)          - execute a command on a remote system, but with the local environment
pack            pack (1)        - compress and expand files
page            more (1)        - browse or page through a text file
pagesize        pagesize (1)    - display the size of a page of memory
passmgmt        passmgmt (1m)   - password files management
passwd          passwd (1)      - change login password and password attributes
passwd          passwd (4)      - password file
paste           paste (1)       - merge corresponding or subsequent lines of files
paste           paste (1)       - merge lines of files
patch           patch (1)       - apply changes to files
patch           patch (1)       - apply a diff file to an original
pathchk         pathchk (1)     - check path names
pathchk         pathchk (1)     - check whether file names are valid or portable
pax             pax (1)         - portable archive interchange
pcat            pack (1)        - compress and expand files
pdp11           machid (1)      - get processor type truth value
perl            .IX (1)         - Practical Extraction and Report Language
pg              pg (1)          - files perusal filter for CRTs
pine            pine (1)        - a Program for Internet News and Email
pkginfo         pkginfo (1)     - display software package information
pkginfo         pkginfo (4)     - package characteristics file
pkgmk           pkgmk (1)       - produce an installable package
pkgparam        pkgparam (1)    - displays package parameter values
pkgproto        pkgproto (1)    - generate prototype file entries for input to pkgmk command
pkgtrans        pkgtrans (1)    - translate package format
pr              pr (1)          - print files
pr              pr (1)          - convert text files for printing
prex            prex (1)        - probe external control
printf          printf (1)      - write formatted output
printf          printf (3b)     - formatted output conversion
printf          printf (3s)     - print formatted output
printf          printf (1)      - format and print data
priocntl        priocntl (1)    - display or set scheduling parameters of specified process(es)
priocntl        priocntl (2)    - process scheduler control
ps              ps (1)          - report process status
ps              ps (1b)         - display the status of current processes
putdev          putdev (1m)     - edits device table
putdgrp         putdgrp (1m)    - edits device group table
pvs             pvs (1)         - display the internal version information of dynamic objects
pwconv          pwconv (1m)     - installs and updates /etc/shadow with information from /etc/passwd
pwd             pwd (1)         - return working directory name
pwd             pwd (1)         - print name of current/working directory
rcp             rcp (1)         - remote file copy
rdate           rdate (1m)      - set system date from a remote host
rdist           rdist (1)       - remote file distribution program
read            read (1)        - read a line from standard input 
read            read (2)        - read from file
read            read (9e)       - read data from a device
red             ed (1)          - text editor
refer           refer (1)       - expand and insert references from a bibliographic database
remsh           rsh (1)         - remote shell
renice          renice (1)      - alter priority of running processes
rksh            ksh (1)         - KornShell, a standard/restricted command and programming language
rlogin          rlogin (1)      - remote login
rm              rm (1)          - remove directory entries
rm              rm (1)          - remove files
rmail           mail (1)        - read mail or send mail to users
rmdir           rm (1)          - remove directory entries
rmdir           rmdir (2)       - remove a directory
rmdir           rmdir (1)       - remove empty directories
roffbib         roffbib (1)     - format and print a bibliographic database
rpcgen          rpcgen (1)      - an RPC protocol compiler
rpcinfo         rpcinfo (1m)    - report RPC information
rsh             rsh (1)         - remote shell
rsh             rsh (1m)        - restricted shell command interpreter
rup             rup (1)         - show host status of remote machines (RPC version)
rup             rup (1c)        - show host status of remote machines (RPC version)
ruptime         ruptime (1)     - show host status of local machines
rusers          rusers (1)      - who's logged in on remote machines
rusers          rusers (3n)     - return information about users on remote machines
rwho            rwho (1)        - who's logged in on local machines
sag             sag (1)         - system activity graph
sar             sar (1)         - system activity reporter
sar             sar (1m)        - system activity report package
savecore        savecore (1m)   - save a core dump of the operating system
script          script (1)      - make record of a terminal session
sdiff           sdiff (1)       - print differences between two files side-by-side
sed             sed (1)         - stream editor
sed             sed (1b)        - stream editor
setfacl         setfacl (1)     - modify the Access Control List (ACL) for a file or files
setpgrp         setpgrp (2)     - set process group ID
setuname        setuname (1m)   - changes machine information
sh              sh jsh          - shell: the standard shell, and job control shell (1)  -- command interpreters
showrev         showrev (1m)    - show machine and software revision information
sleep           sleep (1)       - suspend execution for an interval
sleep           sleep (3b)      - suspend execution for interval
sleep           sleep (3c)      - suspend execution for interval
sleep           sleep (1)       - delay for a specified amount of time
soelim          soelim (1)      - resolve and eliminate .so requests from nroff or troff input
solstice        solstice (1m)   - access system administration tools with a graphical user interface
sort            sort (1)        - sort, merge, or sequence check text files
sort            sort (1)        - sort lines of text files
sortbib         sortbib (1)     - sort a bibliographic database
sparc           machid (1)      - get processor type truth value
spell           spell (1)       - report spelling errors
spline          spline (1)      - interpolate smooth curve
split           split (1)       - split a file into pieces
split           split (1)       - split a file into pieces
srchtxt         srchtxt (1)     - display contents of, or search for a text string in, message data bases
strace          strace (1m)     - print STREAMS trace messages
strchg          strchg (1)      - change or query stream configuration
strclean        strclean (1m)   - STREAMS error logger cleanup program
strconf         strchg (1)      - change or query stream configuration
strerr          strerr (1m)     - STREAMS error logger daemon
strings         strings (1)     - find printable strings in an object or binary file
strings         strings (1)     - print the strings of printable characters in files 
stty            stty (1)        - set the options for a terminal
stty            stty (1b)       - set the options for a terminal
stty            stty (1)        - change and print terminal line settings
su              su (1m)         - become super-user or another user
sum             sum (1)         - print checksum and block count for a file
sum             sum (1b)        - calculate a checksum for a file
sum             sum (1)         - checksum and count the blocks in a file
sun             machid (1)      - get processor type truth value
sync            sync (1m)       - update the super block
sync            sync (2)        - update super block
tabs            tabs (1)        - set tabs on a terminal
tail            tail (1)        - deliver the last part of a file
tail            tail (1)        - output the last part of files
talk            talk (1)        - talk to another user
tar             tar (1)         - create tape archives and add or extract files
tbl             tbl (1)         - format tables for nroff or troff
tcopy           tcopy (1)       - copy a magnetic tape
tcsh            tcsh (1)        - C shell with file name completion and command line editing
tee             tee (1)         - replicate the standard output
tee             tee (1)         - read from standard input and write to standard output and files
telnet          telnet (1)      - user interface to a remote system using the TELNET protocol
test            if (1)          - evaluate condition(s) or make execution of actions dependent upon the evaluation of condition(s)
test            test (1b)       - condition evaluation command
test            test (1f)       - condition evaluation command
test            test (1)        - check file types and compare values
tftp            tftp (1)        - trivial file transfer program
tic             tic (1m)        - terminfo compiler
time            time (1)        - time a simple command
time            time (2)        - get time
timex           timex (1)       - time a command; report process data and system activity
tip             tip (1)         - connect to remote system
tnfdump         tnfdump (1)     - converts binary TNF file to ASCII
tnfxtract       tnfxtract (1)   - extract kernel probes output into a trace file
touch           touch (1)       - change file access and modification times
touch           touch (1b)      - change file access and modification times
touch           touch (1)       - change file timestamps
tplot           tplot (1)       - graphics filters for various plotters
tput            tput (1)        - initialize a terminal or query terminfo database
tr              tr (1)          - translate characters
tr              tr (1b)         - translate characters
tr              tr (7d)         - IBM 16/4 Token Ring Network Adapter device driver
tr              tr (1)          - translate or delete characters
troff           troff (1)       - typeset or format documents
true            true (1)        - provide truth values
true            true (1)        - do nothing, successfully
truss           truss (1)       - trace system calls and signals
tty             tty (1)         - return user's terminal name
tty             tty (7d)        - controlling terminal interface
tty             tty (1)         - print the file name of the terminal connected to standard input
type            type (1)        - write a description of command type
u370            machid (1)      - get processor type truth value
u3b             machid (1)      - get processor type truth value
u3b15           machid (1)      - get processor type truth value
u3b2            machid (1)      - get processor type truth value
u3b5            machid (1)      - get processor type truth value
ul              ul (1)          - do underlining
ulimit          limit (1)       - set or get limitations on the system resources available to the current shell and its descendents
ulimit          ulimit (2)      - get and set process limits
umask           umask (1)       - get or set the file mode creation mask
umask           umask (2)       - set and get file creation mask
unalias         alias (1)       - create or remove a pseudonym or shorthand for a command or series of commands 
uname           uname (1)       - print name of current system
uname           uname (2)       - get name of current operating system
uname           uname (1)       - print system information
uncompress      compress (1)    - compress, uncompress files or display expanded files
unexpand        expand (1)      - expand TAB characters to SPACE characters, and vice versa
unexpand        unexpand (1)    - convert spaces to tabs
uniq            uniq (1)        - report or filter out repeated lines in a file
uniq            uniq (1)        - remove duplicate lines from a sorted file
units           units (1)       - converts quantities expressed in standard scales to other scales
unix2dos        unix2dos (1)    - convert text file from ISO format to DOS format
unpack          pack (1)        - compress and expand files
unzip           unzip (1)       - list, test and extract compressed files in a ZIP archive .PD .\" =========================================================================
uptime          uptime (1)      - show how long the system has been up
uucp            uucp (1c)       - UNIX-to-UNIX system copy
uudecode        uuencode (1c)   - encode a binary file, or decode its encoded representation
uuencode        uuencode (1c)   - encode a binary file, or decode its encoded representation
uuglist         uuglist (1c)    - print the list of service grades that are available on this UNIX system
uulog           uucp (1c)       - UNIX-to-UNIX system copy
uuname          uucp (1c)       - UNIX-to-UNIX system copy
uupick          uuto (1c)       - public UNIX-to-UNIX system file copy
uustat          uustat (1c)     - uucp status inquiry and job control
uuto            uuto (1c)       - public UNIX-to-UNIX system file copy
uux             uux (1c)        - UNIX-to-UNIX system command execution
vacation        vacation (1)    - reply to mail automatically
vax             machid (1)      - get processor type truth value
vedit           vi (1)          - screen-oriented (visual) display editor based on ex
vgrind          vgrind (1)      - grind nice program listings
vi              vi (1)          - screen-oriented (visual) display editor based on ex
view            vi (1)          - screen-oriented (visual) display editor based on ex
vmstat          vmstat (1m)     - report virtual memory statistics
volcheck        volcheck (1)    - checks for media in a drive and by default checks all floppy media
vsig            vsig (1f)       - synchronize a co-process with the controlling FMLI application
w               w (1)           - display information about currently logged-in users
wait            wait (1)        - await process completion
wait            wait (2)        - wait for child process to stop or terminate
wait            wait (3b)       - wait for process to terminate or stop
wc              wc (1)          - display a count of lines, words and characters in a file
wc              wc (1)          - print the number of bytes, words, and lines in files
wchrtbl         chrtbl (1m)     - generate character classification and conversion tables
whatis          whatis (1)      - display a one-line summary about a keyword
which           which (1)       - locate a command; display its pathname or alias
who             who (1)         - who is on the system
who             who (1)         - show who is logged on
whois           whois (1)       - Internet user name directory service
write           write (1)       - write to another user
write           write (2)       - write on a file
write           write (9e)      - write data to a device
xargs           xargs (1)       - construct argument lists and invoke utility
xargs           xargs (1)       - build and execute command lines from standard input
xgettext        xgettext (1)    - extract gettext call strings from C programs
xstr            xstr (1)        - extract strings from C programs to implement shared strings
ypcat           ypcat (1)       - print values in a NIS database
ypmatch         ypmatch (1)     - print the value of one or more keys from a NIS map
yppasswd        yppasswd (1)    - change your network password in the NIS database
ypwhich         ypwhich (1)     - return name of NIS server or map master
zcat            compress (1)    - compress, uncompress files or display expanded files
zcat            gzip (1)        - compress or expand files
zcat            gzip (1)        - compress or expand files
zcat            gzip (1)        - compress or expand files
zipinfo         zipinfo (1)     - list detailed information about a ZIP archive

--- Obsolete; not used
<show_debug>
parameter
<SCRIPT>
program test;
	use IDE_tools_pak;		-- 
	show_debug();			-- display the debug information collected by executing a program 
							-- after it has been processed by the debug_setup tool
end test;

<HELP>
This tool displays the debug information collected by executing a program after it has been processed by the debug_setup tool, and then immediately executed. It can also remove the insertions made by the debug_setup tool.

<show_data>
parameter
<SCRIPT>
program test;					-- display the debug information collected by executing a program 
								-- after it has been processed by the debug_setup tool
	use IDE_tools_pak,IDE_pak,sort_pak,string_utility_pak;

	[cycle_no,data] := unstr(get_pdata());
	drop_pos := get_position();
	text := get_buffer();
	line_no := #(breakup(text(1..drop_pos),"\r\n"));
	print("line_no: ",line_no," cycle: ",cycle_no(line_no)); 
	for [name,val] in merge_sort(data(line_no)) loop
		print("\t\t",name,":    ",val);
	end loop;
end test;

<HELP>
Once a program has been processed by using the debug_setup tool, then immediately executing the program, and then using the show_debug tool, dropping this tool on any program line will display the values that all variables in the line had immediately after the line was executed.


